в 90-х у меня был бумажный справочник стандарта C и в нем было написано, что это должен быть массив ссылок. За ссылку на дафт спасибо, очень забавный документ, триграфы, значит, они сохранили, лол.
Но, возвращаясь к многомерным массивам. Вы совершенно правильно заметили, что их в C нет. Давайте же разберем, что значит [] в C. С одномерным массивом всё понятно:
char x[10];
Тип переменной x тут -- указатель char*, с этим не будете спорить? Пойдем далее, какой тип у x в этом коде:
char x[10][10];
? Возьму на себя смелость утверждать, что это будет char**, то есть указатель на массив указателей. Какие действия нужно произвести, чтобы получить доступ к элементу x[3][3]? Начнем с простого -- в результате будет определенно char. Как мы могли бы получить char из char*? Нам нужно разыменование указателя, то есть мы берем адрес из char*, обращаемся к памяти по этому адресу и получаем искомый char. Но у нас не char*, у нас char**. Разыменованием мы получим char*, то есть char** это указатель на массив (в нашем случае) указателей. Чтобы получить искомый char, нам нужно разыменовывать указатель дважды. В соответствии со стандартом.
Фактически, код:
char c=x[3][3];
эквивалентен коду:
char c=*(*(x+3)+3);
То, что компилятор делает оптимизацию, превращая массив в фортрановский (да, массивы такого типа так называются), нарушает стандарты. Если я в другом месте (а лучше всего, в другом объектном файле или библиотеке) попытаюсь дважды разыменовать указатель char **x, то получу в лучшем случае SIGSEGV, в худшем -- рандомное значение.
Фактически, компилятор может хранить массив по-фортрановски, а для внешних вызовов сделать массив указателей, чтобы сохранить совместимость. Отлично. Но функция, получившая этот указатель, будет обязана разыменовывать указатели как положено, делая по нескольку лишних запросов в память, с этим ничего не поделаешь. И именно на эти грабли обычно наступают студенты и аспиранты)
Именно, в стандарте С написано, что многомерный массив -- это массив ссылок на одномерные массивы. Если компилятор хранит массив иным образом -- это нарушение. И, да, вполне возможно, что все (современные) компиляторы этим грешат для оптимизации. Компилятор знает, что программист не использует эту фишку (в ваших примерах это можно определить) и хранит массивы так. А теперь представьте, что этот массив надо экспортировать -- вызвать внешнюю функцию и передать ссылку на массив. Если у компилятора нет возможности делать межобъектную оптимизацию (у Intel C/C++ для этого нужно использовать специальный ключ, например), он вынужден будет хранить массив в соответствии со стандартом, в внешняя функция -- обращаться к нему в соответствии со стандартом. И, здравствуйте, вот вам и лишние обращения к памяти!
Отличный пример! Тут компилятор явно нарушает стандарт, используя массивы в "фортрановском стиле", например, интеловский компилятор так делает. Проблема в том, что делает он так не всегда)
С рестартами вряд ли получится. Они позволяют, например, вместо выражения, вызвавшего исключение, выполнить другое и продолжить выполнение. Сохранить контекст и потом восстановить его в произвольный момент времени они не могут.
Скорее, не к процессору, а просто для других вещей был предназначен. Самое вопиющее различие -- многомерные массивы. В фортране для доступа к произвольному элементу требуется одно обращение к памяти (чаще всего). В Си -- столько, сколько измерений у массива. На эти грабли, как правило, наступает каждый аспирант, загоревшийся идеей переписать код с фортрана на Си и потом недоумевающий, почему его версия работает в несколько раз медленнее)
Мне всегда казалось, что смысл генераторов именно в функции yield, когда код генератора непрерывен и может возвращать данные из любой точки, продолжая выполнение с того же места по вызову next. В CL есть некоторые проблемы с таким подходом, так как для его реализации нужен call/cc, а он конфликтует с unwind-protect и простого решения тут нет. Именно по этой причине генераторов нет в CL.
Учитывая, что на устройстве уже работает целое приложение, чем это увеличит опасность? Да и JS работает в песочнице. Если бояться JS, то в интернет лучше вообще не заходить)
Фортран очень простой и "приземленный" язык, в том смысле, что все вещи в фортране делаются практически всегда так, как они делаются процессором. Это позволяет делать очень хорошие оптимизирующие компиляторы, так как компилятору не нужно предусматривать хитровыдуманные способы взаимодействия с памятью, как в других языках. Фортран примитивен, он просто не позволит тебе использовать конструкции, которые нельзя эффективно скомпилировать. Это не отменяет возможности "грязных хаков", конечно, но если ты применил то, что применять не стоило и это не сработало -- ты сам себе буратино. К тому же компиляторы фортрана (а их много!) разрабатываются и конкурируют между собой уже более полувека, они прошли большой путь эволюции и нагнать их другим языкам будет непросто. К тому же, в наш век опенсорса, конкуренция компиляторов уже мало возможна. Много ли конкурирующих компиляторов питона, например? Если какой-то фирме захочется создать такой, сможет ли она на нем зарабатывать? Вряд ли. По этой причине Фортран так и останется самым быстрым языком для научных вычислений)
странно, но почти в 100% случаях я нахожу себя поуши в чужих исходниках, если что-то не работает) Ни разу не видел документации, которая помогла бы решить по-настоящему серьезную проблему просто по результатам ее чтения)
Жутко бесит всплывающая реклама в мобильных версиях сайтов. В наиболее упоротых случаях сначала всплывает рекламный блок снизу, оставляя только половину экрана с контентом, потом сразу же всплывает рекламный блок сверху, закрывая вторую половину.
Тут, конечно, отчасти сарказм, но только отчасти. Эффект такой действительно есть, много раз его наблюдал. Как только кольца встали, по радальным магистралями становится проще проехать.
Но тут есть и неявный плюс. В Москве, например, кольца, когда встают (а встают они регулярно, в силу своей природы) всасывают в себя огромное количество машин. При этом, парадоксальным образом, разгружаются радиальные магистрали. У меня были очень большие надежды, в этом смысле, на четвертое транспортное кольцо и я очень огорчился, когда от него отказались.
В идеальном мире, наверное, можно совместить "красиво" и "удобно". Но в реальности, почему-то, в лучшем случае получается только что-нибудь одно. И то довольно редко.
Если нужно что-то планировать и писать отчеты в дороге, то удобнее всего автомобиль с водителем или такси, что мало от личного транспорта отличается. Ну и 2-4 рабочих поездки в день, всё же довольно маргинальный случай. Большинству нужно утром на работу приехать и вечером уехать, по дороге заехав в магазин за продуктами.
В реальной жизни всегда есть некий трейд между "красиво" и "удобно". Перемещаться удобнее всего на личном автомобиле (особенно в зимний период), но парковки и автострады это некрасиво. Велосипеды и моноколеса это красиво, но в мороз несколько неудобно. Ларьки у метро это удобно, можно быстро купить зарядник для телефона и шаурму, проходя мимо. Но некрасиво. Гранитная плитка очень красива, но ходить по ней неудобно. И так далее.
Адепты "урбанизма" пытаются перетянуть одеяло в сторону "красиво", но уменьшают удобство жизни в целом, что мы видим на примене собяниновской Москвы, например. Тут есть некоторая логика -- невозможно упихать столько народу на такой ограниченной площади, сохранив удобство, но можно сделать красиво, что и делается. Однако, это "ложная дихотомия" -- тут неявно предполагается, что плотность населения нужно увеличивать. Зачем ее увеличивать? Если плотность населения уменьшить, расселить крупные города, то удобство и красоту получится совместить.
И при всем при этом внутреннее представление квазицитирования до сих пор не стандартизовано в CL. Никаких тебе quasiquote, unquote и пр., каждый компилятор сам решает, как это представлять. И ведь столько лет прошло.
в 90-х у меня был бумажный справочник стандарта C и в нем было написано, что это должен быть массив ссылок. За ссылку на дафт спасибо, очень забавный документ, триграфы, значит, они сохранили, лол.
Но, возвращаясь к многомерным массивам. Вы совершенно правильно заметили, что их в C нет. Давайте же разберем, что значит [] в C. С одномерным массивом всё понятно:
Тип переменной
x
тут -- указательchar*
, с этим не будете спорить? Пойдем далее, какой тип уx
в этом коде:? Возьму на себя смелость утверждать, что это будет
char**
, то есть указатель на массив указателей. Какие действия нужно произвести, чтобы получить доступ к элементуx[3][3]
? Начнем с простого -- в результате будет определенноchar
. Как мы могли бы получитьchar
изchar*
? Нам нужно разыменование указателя, то есть мы берем адрес изchar*
, обращаемся к памяти по этому адресу и получаем искомыйchar
. Но у нас неchar*
, у насchar**
. Разыменованием мы получимchar*
, то естьchar**
это указатель на массив (в нашем случае) указателей. Чтобы получить искомый char, нам нужно разыменовывать указатель дважды. В соответствии со стандартом.Фактически, код:
эквивалентен коду:
То, что компилятор делает оптимизацию, превращая массив в фортрановский (да, массивы такого типа так называются), нарушает стандарты. Если я в другом месте (а лучше всего, в другом объектном файле или библиотеке) попытаюсь дважды разыменовать указатель
char **x
, то получу в лучшем случаеSIGSEGV
, в худшем -- рандомное значение.Фактически, компилятор может хранить массив по-фортрановски, а для внешних вызовов сделать массив указателей, чтобы сохранить совместимость. Отлично. Но функция, получившая этот указатель, будет обязана разыменовывать указатели как положено, делая по нескольку лишних запросов в память, с этим ничего не поделаешь. И именно на эти грабли обычно наступают студенты и аспиранты)
Именно, в стандарте С написано, что многомерный массив -- это массив ссылок на одномерные массивы. Если компилятор хранит массив иным образом -- это нарушение. И, да, вполне возможно, что все (современные) компиляторы этим грешат для оптимизации. Компилятор знает, что программист не использует эту фишку (в ваших примерах это можно определить) и хранит массивы так. А теперь представьте, что этот массив надо экспортировать -- вызвать внешнюю функцию и передать ссылку на массив. Если у компилятора нет возможности делать межобъектную оптимизацию (у Intel C/C++ для этого нужно использовать специальный ключ, например), он вынужден будет хранить массив в соответствии со стандартом, в внешняя функция -- обращаться к нему в соответствии со стандартом. И, здравствуйте, вот вам и лишние обращения к памяти!
Отличный пример! Тут компилятор явно нарушает стандарт, используя массивы в "фортрановском стиле", например, интеловский компилятор так делает. Проблема в том, что делает он так не всегда)
С рестартами вряд ли получится. Они позволяют, например, вместо выражения, вызвавшего исключение, выполнить другое и продолжить выполнение. Сохранить контекст и потом восстановить его в произвольный момент времени они не могут.
Скорее, не к процессору, а просто для других вещей был предназначен. Самое вопиющее различие -- многомерные массивы. В фортране для доступа к произвольному элементу требуется одно обращение к памяти (чаще всего). В Си -- столько, сколько измерений у массива. На эти грабли, как правило, наступает каждый аспирант, загоревшийся идеей переписать код с фортрана на Си и потом недоумевающий, почему его версия работает в несколько раз медленнее)
Мне всегда казалось, что смысл генераторов именно в функции
yield
, когда код генератора непрерывен и может возвращать данные из любой точки, продолжая выполнение с того же места по вызовуnext
. В CL есть некоторые проблемы с таким подходом, так как для его реализации нуженcall/cc
, а он конфликтует сunwind-protect
и простого решения тут нет. Именно по этой причине генераторов нет в CL.Учитывая, что на устройстве уже работает целое приложение, чем это увеличит опасность? Да и JS работает в песочнице. Если бояться JS, то в интернет лучше вообще не заходить)
Собственно, BASIC был как раз таким языком в свое время. Все начинали с него. И где теперь BASIC? Вот и питон там же будет)
Фортран очень простой и "приземленный" язык, в том смысле, что все вещи в фортране делаются практически всегда так, как они делаются процессором. Это позволяет делать очень хорошие оптимизирующие компиляторы, так как компилятору не нужно предусматривать хитровыдуманные способы взаимодействия с памятью, как в других языках. Фортран примитивен, он просто не позволит тебе использовать конструкции, которые нельзя эффективно скомпилировать. Это не отменяет возможности "грязных хаков", конечно, но если ты применил то, что применять не стоило и это не сработало -- ты сам себе буратино. К тому же компиляторы фортрана (а их много!) разрабатываются и конкурируют между собой уже более полувека, они прошли большой путь эволюции и нагнать их другим языкам будет непросто. К тому же, в наш век опенсорса, конкуренция компиляторов уже мало возможна. Много ли конкурирующих компиляторов питона, например? Если какой-то фирме захочется создать такой, сможет ли она на нем зарабатывать? Вряд ли. По этой причине Фортран так и останется самым быстрым языком для научных вычислений)
Что я обычно говорю аспирантам в таких ситуациях: самое лучшее оправдание всё равно хуже, чем самый плохонький результат)
странно, но почти в 100% случаях я нахожу себя поуши в чужих исходниках, если что-то не работает) Ни разу не видел документации, которая помогла бы решить по-настоящему серьезную проблему просто по результатам ее чтения)
Жутко бесит всплывающая реклама в мобильных версиях сайтов. В наиболее упоротых случаях сначала всплывает рекламный блок снизу, оставляя только половину экрана с контентом, потом сразу же всплывает рекламный блок сверху, закрывая вторую половину.
строительство это всегда чудовищно дорого
Тут, конечно, отчасти сарказм, но только отчасти. Эффект такой действительно есть, много раз его наблюдал. Как только кольца встали, по радальным магистралями становится проще проехать.
Но тут есть и неявный плюс. В Москве, например, кольца, когда встают (а встают они регулярно, в силу своей природы) всасывают в себя огромное количество машин. При этом, парадоксальным образом, разгружаются радиальные магистрали. У меня были очень большие надежды, в этом смысле, на четвертое транспортное кольцо и я очень огорчился, когда от него отказались.
В идеальном мире, наверное, можно совместить "красиво" и "удобно". Но в реальности, почему-то, в лучшем случае получается только что-нибудь одно. И то довольно редко.
Если нужно что-то планировать и писать отчеты в дороге, то удобнее всего автомобиль с водителем или такси, что мало от личного транспорта отличается. Ну и 2-4 рабочих поездки в день, всё же довольно маргинальный случай. Большинству нужно утром на работу приехать и вечером уехать, по дороге заехав в магазин за продуктами.
В реальной жизни всегда есть некий трейд между "красиво" и "удобно". Перемещаться удобнее всего на личном автомобиле (особенно в зимний период), но парковки и автострады это некрасиво. Велосипеды и моноколеса это красиво, но в мороз несколько неудобно. Ларьки у метро это удобно, можно быстро купить зарядник для телефона и шаурму, проходя мимо. Но некрасиво. Гранитная плитка очень красива, но ходить по ней неудобно. И так далее.
Адепты "урбанизма" пытаются перетянуть одеяло в сторону "красиво", но уменьшают удобство жизни в целом, что мы видим на примене собяниновской Москвы, например. Тут есть некоторая логика -- невозможно упихать столько народу на такой ограниченной площади, сохранив удобство, но можно сделать красиво, что и делается. Однако, это "ложная дихотомия" -- тут неявно предполагается, что плотность населения нужно увеличивать. Зачем ее увеличивать? Если плотность населения уменьшить, расселить крупные города, то удобство и красоту получится совместить.
И при всем при этом внутреннее представление квазицитирования до сих пор не стандартизовано в CL. Никаких тебе
quasiquote
,unquote
и пр., каждый компилятор сам решает, как это представлять. И ведь столько лет прошло.мой способ гибче: