Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Странности при оптимизации
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Страницы: 1, 2
DenisIV
Кстати, раз уж о глюках:

У меня при включенной оптимизации компилятор думает, что раз тела у while нет, то можно и зациклить сам на себя БЕЗ проверки условия, т.е.

MojBit=1;

while(MojBit==1) { };

в асме выглядит так:

Addr: rjmp Addr

Если в тело хотя бы вставить _NOP(); т.е. while(MojBit==1) {_NOP();};

картина меняется - добавляется загрузка вита в 1 и проверка в теле while. Вопрос знатокам: Почему? Компилятор умнее пользователя?

Модератор.
Тема выделена как отдельная из другого топика.
Палыч
Цитата(DenisIV @ Dec 23 2008, 15:40) *
Вопрос знатокам: Почему? Компилятор умнее пользователя?
Почему картина поменялась после добавления _NOP(); - не скажу, вроде на условие в цикле не влияет... А, вот, проверять условие цикла - нет необходимости: переменной MojBit присвоено значение 1 и условие MojBit==1 - всегда выполняется!
scifi
Цитата(DenisIV @ Dec 23 2008, 15:40) *
Вопрос знатокам: Почему? Компилятор умнее пользователя?

Ответ прост: бывают умные компиляторы и не очень умные (ну и тупые тоже бывают). Видимо, Ваш компилятор не очень умный: в одной ситуации может оптимизировать до предела, а в другой - не может.
DenisIV
Цитата(Палыч @ Dec 23 2008, 15:52) *
Почему картина поменялась после добавления _NOP(); - не скажу, вроде на условие в цикле не влияет... А, вот, проверять условие цикла - нет необходимости: переменной MojBit присвоено значение 1 и условие MojBit==1 - всегда выполняется!

Не согласен. Вы забыли про прерывания? Вот они и меняют этот бит. Может компилёру нужно дополнительно сообщить, что этот бит ещё где-то может модифицироваться? Вопрос, как...
P.S. Я с асмом дружу очень, но большие модули переписываю на С, потому что надоело при смене типа мк в пределах одного изготовителя приходится сильно менять исходник, а при смене Z80<>PIC<>Holtek<>AVR<>msp430<>PC<>mcs48<>mcs51 и т.д. просто волосы дыбом встают...
Поэтому и прошу помощи... Как было указано в начале темы, мож у мя глюки?
2Moderator: Может мне создать отдельную тему? Но я её хотел назвать именно так, как назвал авторsmile.gif
Nemo2000
Цитата(DenisIV @ Dec 23 2008, 21:37) *
Вы забыли про прерывания? Вот они и меняют этот бит. Может компилёру нужно дополнительно сообщить, что этот бит ещё где-то может модифицироваться?


а прочитать тему с самого начала?
при объявлении своей переменной MojBit укажите что она volatile и будет вам счастье
sergeeff
Просто не устаю поражаться. На нашем форуме про volatile уж было все рассказано, подробнее, чем где-бы то ни было, учитывая специфику программирования железа. Ан нет, есть еще граждане про сие не читавшие, да еще и вопрос задающие не поймешь как. Чудно, все это.
DenisIV
Цитата(sergeeff @ Dec 24 2008, 01:38) *
Просто не устаю поражаться. На нашем форуме про volatile уж было все рассказано, подробнее, чем где-бы то ни было, учитывая специфику программирования железа. Ан нет, есть еще граждане про сие не читавшие, да еще и вопрос задающие не поймешь как. Чудно, все это.


Прошу простить... Это как допустим чья-то жена получила вчера права, начинает спрашивать мужа: "Как там решить вопрос с ГАИшниками, если..." Муж: "Я ж те говорил, книжки покупал..."

На сколько я знаю, volatile говорит компилятору о том, что все связанные с переменной действия ни в коем случае не оптимизировать. Вопрос для многозадачных или "мощных" систем вроде выглядит по другому: требуется ещё лочить переменную на время обработки данных(например в прерывании меняется массив данных и указатели на него а основная прога может вылететь) И если можно про static.

Просветите плиз тонкости... Может быть еще раз... Ну "я месяц назад получил права" smile.gif
rezident
Цитата(DenisIV @ Dec 24 2008, 04:21) *
И если можно про static.

Просветите плиз тонкости... Может быть еще раз... Ну "я месяц назад получил права" smile.gif
Вот тут не найдется для вас ответа на вопрос про static?
sergeeff
Цитата(DenisIV @ Dec 24 2008, 03:21) *
Прошу простить... Это как допустим чья-то жена получила вчера права, начинает спрашивать мужа: "Как там решить вопрос с ГАИшниками, если..." Муж: "Я ж те говорил, книжки покупал..."

На сколько я знаю, volatile говорит компилятору о том, что все связанные с переменной действия ни в коем случае не оптимизировать. Вопрос для многозадачных или "мощных" систем вроде выглядит по другому: требуется ещё лочить переменную на время обработки данных(например в прерывании меняется массив данных и указатели на него а основная прога может вылететь) И если можно про static.

Просветите плиз тонкости... Может быть еще раз... Ну "я месяц назад получил права" smile.gif


Во-первых, понять, что если есть в системе прерывания и вы их используете - значит уже система многозадачная. Во-вторых. Что значит "приказ не оптимизировать"? Это значит, что какая-то другая задача тоже может эту переменную использовать, а по сему эта самая переменная будет размещена в памяти, а не в регистрах. Вопрос о том, "лочить" или нет эту переменную - вопрос ее размера и особенностей процессора. Если обращение к ней проходит за время, когда прерывание не может возникнуть, то и "лочить" не нужно.
DenisIV
2rezident: со static (и не тоько) разобрался, спасибо!

Ещё вопросик...

Насколько я понимаю, у меня эти проблемы с оптимизацией начались после того, как у меня образовалось более одного модуля, т.е. каждый модуль независим для компилятора и компилёр оптимизирует не проект, а данный модуль и если я в одном модуле только читаю а в другом только пишу переменную, то в обоих случаях если я не допишу volatile компилёр просто выкинет эти строки (просто примет за константу данные при компиляции), а с линкера не спросишь-он просто склеит готовые блоки.

Опять же, если будет это всё в одном файле/модуле, то даже при макс. оптимизации компилёр может понять, что переменная юзается внутри в разных функциях (в т.ч и в прерываниях) и не будет оптимизировать до упора?

Т.е. в данном случае не нужен тип global/static/volatile ? (модуль-то один, global итак будет автоматом, вопрос только про оптимизатор)

Да, самое интересное: Я объявляю в модуле main глобальные переменные, в остальных модулях их же, но через extern, т.е. получается, что глобально в пределах проекта, но вот эта заноза-оптимизатор видит только в пределах модуля переменную (в смысле её использования), а не в пределах проекта? Или есть тонкости? Объясните плиз, где грабли... Крыша уже течёт...

Просто я не умею их готовить... (с) какая-то реклама

Чем-то чувствую, что и прав и нет. Хотелось бы понять, где. Я понимаю, RTFM, но всё же... F1 !
То, что люди задают глупые вопросы не означает, что они глупы, просто иногда не хватает опыта...
Сорри, если чуть оффтоп... wink.gif
sergeeff
Я все не пойму, что за проблемы "с этой оптимизацией"? Где конкретно, с чем проблемы? Что компилятор делает не так, как вы хотите?
DenisIV
Цитата(sergeeff @ Dec 24 2008, 15:41) *
Я все не пойму, что за проблемы "с этой оптимизацией"? Где конкретно, с чем проблемы? Что компилятор делает не так, как вы хотите?

Каждый модуль независим для компилятора и компилёр оптимизирует не проект, а данный модуль и если я в одном модуле только читаю а в другом только пишу переменную, то в обоих случаях если я не допишу volatile компилёр просто выкинет эти строки (просто примет за константу данные при компиляции)
Вот в этом и грабли. Всё могло быть хорошо, если модуль один. (Вроде бы)
XVR
Цитата(DenisIV @ Dec 24 2008, 15:55) *
Каждый модуль независим для компилятора и компилёр оптимизирует не проект, а данный модуль и если я в одном модуле только читаю а в другом только пишу переменную, то в обоих случаях если я не допишу volatile компилёр просто выкинет эти строки (просто примет за константу данные при компиляции)
Нет. Компилятор ОБЯЗАН обеспечить состояние переменных, видимое с точки зрения программиста, в любой точке программы. volatile всего лишь заставляет компилятор считать, что состояние переменной может быть изменено не только тем, что написанно в программе. Т.е. компилятор не имеет права выкидывать любые записи и чтения этой переменной. Но он не обязан каким либо другим способом синхронизировать доступ к ней - это обязанность программиста.

Например, если мы имеем код

Код
a=1;

...

a=2;

...

a=3;
то для не volatile переменной компилятор может оставить только последнее присваивание (если в промежутке не было вызовов других функций), для volatile все присваивания останутся



Цитата
Вот в этом и грабли. Всё могло быть хорошо, если модуль один. (Вроде бы)
От количества модулей это не зависит. А вот качество оптимизации может зависеть.
DenisIV
Цитата(XVR @ Dec 24 2008, 17:13) *
Нет. Компилятор ОБЯЗАН обеспечить состояние переменных, видимое с точки зрения программиста, в любой точке программы. volatile всего лишь заставляет компилятор считать, что состояние переменной может быть изменено не только тем, что написанно в программе. Т.е. компилятор не имеет права выкидывать любые записи и чтения этой переменной. Но он не обязан каким либо другим способом синхронизировать доступ к ней - это обязанность программиста.

Например, если мы имеем код

Код
a=1;
...
a=2;
...
a=3;
то для не volatile переменной компилятор может оставить только последнее присваивание (если в промежутке не было вызовов других функций), для volatile все присваивания останутся

От количества модулей это не зависит. А вот качество оптимизации может зависеть.

Согласен. А есть ли возможность указать компилятору в данном конкретном примере какой-нибудь командой #cmdxxx НЕ ОПТИМИЗИРОВАТЬ например именно строчку где a=2; ?
sergeeff
Уважаемый DenisIV!
Если вы хотите быть "более продвинутым компилятором", чем имеющийся в вашем распоряжении компилятор, то вам надо это написать на ассемблере и тогда там точно будет выполняться то, что вы сами напишете. Но я все равно в толк не возьму, что за странные оптимизационные трюки вы хотите выполнять? На кой вам это сдалось?

Я уже раньше отмечал, что современные компиляторы занимаются оптимизацией совместно с линкером. Об этом и Александреску в своих книгах пишет. Да и сами можете убедиться, сравнив ассемблерный листинг, генерируемый компилятором и дизассемблированный код. Так что замечания насчет оптимизации на уровне модуля тоже не совсем правомочны.
defunct
Цитата(DenisIV @ Dec 24 2008, 17:47) *
А есть ли возможность указать компилятору в данном конкретном примере какой-нибудь командой #cmdxxx НЕ ОПТИМИЗИРОВАТЬ например именно строчку где a=2; ?

#pragma optimize = none
zltigo
Цитата(sergeeff @ Dec 24 2008, 19:26) *
Я уже раньше отмечал, что современные компиляторы занимаются оптимизацией совместно с линкером. Об этом и Александреску в своих книгах пишет.

Про "оптимизирующий" код линкер это достойно назаборной письменности.
sergeeff
Цитата(zltigo @ Dec 24 2008, 21:35) *
Про "оптимизирующий" код линкер это достойно назаборной письменности.


К примеру, начиная с MSVC++ 7.0 линкер имеет опцию /ltcg - "link time code generation" и это позволяет "отодвинуть" вопрос о встраивании функции или использовании обычного вызова на этап линковки. Про это достаточно подробно Г.Саттер "Новые сложные задачи на С++", Вильямс, 2005 стр.164-174. Нечто подобное поддерживает компилятор от HP.
zltigo
Цитата(sergeeff @ Dec 25 2008, 01:09) *
К примеру

К "примеру" Вы уже говорили:
Цитата
сравнив ассемблерный листинг, генерируемый компилятором и дизассемблированный код. Так что замечания насчет оптимизации на уровне модуля тоже не совсем правомочны.

А вот это:
Цитата
и это позволяет "отодвинуть" вопрос о встраивании функции или использовании обычного вызова на этап линковки.

уже не имеет нималейшего отношения ни к обсуждаемой "проблеме", ни к Вашим предыдущим словам. Не говоря уже о том, что это вполне бесполезный трюк, ибо не позволяет произвести сквозную оптимизацию "склееенного" кода, а только грошовую экономию вызова. Любой компилятор сделает СВОЮ работу по inline несораизмеримо лучше, при этом КОМПИЛЯТОР должен предавительно изменить calling conversion для тех функций которые предполагается потом возможно склеить.
sergeeff
Я не являюсь разрабочиком компиляторов и линкеров. Все вышесказанное привел только для иллюстрации того, что на сегодняшний день не только компилятор, но и линкер совместно оптимизируют генерируемый код. Это может кому-то нравится, а кому-то нет.
XVR
Цитата(sergeeff @ Dec 25 2008, 04:16) *
Я не являюсь разрабочиком компиляторов и линкеров.
Я являюсь smile.gif

Цитата
Все вышесказанное привел только для иллюстрации того, что на сегодняшний день не только компилятор, но и линкер совместно оптимизируют генерируемый код.
Это не совсем точное высказывание sad.gif Код может оптимизироваться на этапе линковки, но занимается этим не линкер, а все таки компилятор. И тот 'код', который оптимизируется, на самом делен не код, а промежуточное представление компилятора.

Цитата
Это может кому-то нравится, а кому-то нет.
Вне зависимости от того, нравится это или нет, оптимизациями занимается компилятор, когда бы он не запускался 1111493779.gif

Пример: Hi-TECH PICC-18 Pro. Результатом независимой компиляции модуля (.c) является файл (.p1) с промежуточным представлением С'ной программы. На этапе сборки (линковки) они ВМЕСТЕ обрабатываются компилятором, который и генерит выходной код.

Другой пример: Intel C компилятор. Опция -ipo (или -fast) переводит компилятор в режим компиляции всей программы. При этом, компиляция собственно модулей (.c) производит .obj файлы, в которых НЕТ кода, зато есть секции с промежуточным представлением программы. На этапе линковки снова вызывается компилятор, который читает все это из .obj файлов и генерирует код (в виде одного .obj файла, на этот раз с кодом) который уже и отправляется линкеру.

Что касается опции 'MSVC++ 7.0 /ltcg' то сдается мне, что это не опция линкера, а опция ВСЕГО проекта, и подавать ее надо везде. Реализация (скорее всего) будет очень похожа на реализацию в Intel компиляторе

Единственная известная мне 'оптимизация' именно ЛИНКЕРА - это выкидывание неиспользуемых кодов и данных из исполняемого файла. Но у меня язык не повернется назвать это 'оптимизацией' sad.gif
Сергей Борщ
Цитата(XVR @ Dec 25 2008, 09:17) *
Вне зависимости от того, нравится это или нет, оптимизациями занимается компилятор, когда бы он не запускался 1111493779.gif
Не во всех компиляторах. В avr-gcc вызов линкера с опцией --relax приводит к замене пар call/ret на jmp, а jmp (там, где длина перехода позволяет) - на rjmp. Это вполне себе оптимизация и занимается ей именно линкер.
DenisIV
Цитата(defunct @ Dec 24 2008, 20:09) *
#pragma optimize = none

Спасибо. Это как раз и было нужно. А опять включить ?
Или можно поменять степень оптимизации на ходу?
Сергей Борщ
Цитата(DenisIV @ Dec 25 2008, 15:17) *
Спасибо. Это как раз и было нужно. А опять включить ?
Или можно поменять степень оптимизации на ходу?
Вы двигаетесь в неправильном направлении. Правильно написанная программа должна работать при любом уровне оптимизации.
DenisIV
Цитата(Сергей Борщ @ Dec 25 2008, 16:24) *
Вы двигаетесь в неправильном направлении. Правильно написанная программа должна работать при любом уровне оптимизации.

Согласен. Но в данном случае вы неправы. Бывают разные ситуации. Я, например в данном случае пытаюсь добиться результатов после дилетанта-программиста. Возможности переписать ВСЮ прогу просто нет, отключаю оптимизацию=прога не влазит в кристалл. Программист в прерываниях использует почти все модули и я исправляю ошибки доступа, что бы основная прога не вешалась. Так что в данном случае мой вопрос правилен.
Лично я пишу, правильно разбивая ресурсы/переменные и лично у меня проблем с оптимизацией не было.
Просто исправлять за кем-то - неблагодарное и трудное занятие. Но необходимое (в моём случае)
DenisIV
Ещё вопросик:
Например, компилятор HiTech предупреждает при:
Код
while(1)  { .... }
while(1)  { .... }

типа warning: infinity loop, а вот ИАР не предупреждает, а молча делает... smile.gif
Но это лирика...

У меня (в данном случае ИАР) ругается на переменные, когда я их обзываю volatile на то, что он не может просчитать их значение, т.к. не проинициализированы.
А инитить я их не хочу, т.к. эти переменные лежат в озу и должны быть валидны и просле ресета (я их инициализю отдельно, считая их CRC или анализируя флаг сброса по питанию)
Вот тут и грабли... (Опять повторю, прогу полностью переписать не cмогу(высшая математика), исправляю за самоучками sad.gif )
rezident
DenisIV, а такой вариант объявления
Код
__no_init volatile unsigned a, b, c;

не проходит? У меня IAR только "варнингами" ругается, но ошибок не выдает.
DenisIV
Цитата(rezident @ Dec 26 2008, 00:38) *
DenisIV, а такой вариант объявления
Код
__no_init volatile unsigned a, b, c;

не проходит? У меня IAR только "варнингами" ругается, но ошибок не выдает.

Проходит,ошибок нет, вот по этому и спрашиваю, как обойти... Варнинги достали (>100) sad.gif
Мож #pragma optimize =none ?
Ток я не знаю, как потом включить и будут ли варнинги дальше?
А у меня варнинг-указание на засаду в проге. Игнорировать и отключать не хочется... Потом можно 3 дня глюк ловить... И не поймать... sad.gif
Сергей Борщ
Цитата(DenisIV @ Dec 25 2008, 23:19) *
типа warning: infinity loop, а вот ИАР не предупреждает, а молча делает... smile.gif
Но это лирика...
Это не лирика, это где-то у вас преднамеренно отключены предупреждения (Project->Options->C/C++ compiler->Diagnostics):
Код
void Test()
{
    while(1) { __no_operation();}
    while(1) { __no_operation();}
}

Warning[Pe128]: loop is not reachable from preceding code D:\****\loader.cpp 75
Цитата(DenisIV @ Dec 25 2008, 23:19) *
У меня (в данном случае ИАР) ругается на переменные, когда я их обзываю volatile на то, что он не может просчитать их значение, т.к. не проинициализированы.
Давайте так: Есть непонятка, выкладываете код, выкладываете полный текст предупреждения на языке оригинала, будем смотреть.
Код
volatile int a;
volatile int b;
volatile int c;
void Test()
{
    int Tmp = a;
    b = Tmp;
    Tmp = b;
    c = Tmp;
}

Done. 0 error(s), 0 warning(s)

   \                                 In segment DATA_Z, align 4, align-sorted
     72          volatile int a;
   \                     a:
   \   00000000                      DS8 4
     73          volatile int b;
   \                     `b`:
   \   00000004                      DS8 4
     74          volatile int c;
   \                     c:
   \   00000008                      DS8 4

   \                                 In segment CODE, align 4, keep-with-next
     75          void Test()
     76          {
     77              int Tmp = a;
   \                     ??Test:
   \   00000000   0248               LDR         R0,??Test_1      ;; a
   \   00000002   0168               LDR         R1,[R0, #+0]
     78              b = Tmp;
   \   00000004   4160               STR         R1,[R0, #+0x4]
     79              Tmp = b;
   \   00000006   4168               LDR         R1,[R0, #+0x4]
     80              c = Tmp;
   \   00000008   8160               STR         R1,[R0, #+0x8]
     81          }
   \   0000000A   7047               BX          LR            ;; return
   \                     ??Test_1:
   \   0000000C   ........           DC32        a
Как видите, никакой ругани, делает все, как просилось.
Я могу предположить, что ругань выглядит так:
Цитата
Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement D:\*****\loader.cpp 77
Но она означает вовсе не "не может проинициализировать", а "не определен порядок обращения к volatile-переменным". И вызывает его примерно такой код:
Код
int a;
volatile int b;
volatile int c;
void Test()
{
    a = b + c;
}
И это предупреждение совершенно справедливо: стандарт позволяет компилятору изменять порядок вычисления подвыражений. А поскольку одно из свойств volatile-переменных состоит в том, что чтение может изменять ее значение (а таким свойством обладают многие sfr-регистры), то изменение порядка чтения двух volatile-переменных может привести к неожиданным для вас результатам. Поэтому для разрешения неоднозначности надо разделить чтения точками последовательности, т.е. ";" или оператором "запятая", введя временную переменную как я сделал в примере выше.
Но это лишь гадание.Если бы вы представили минимальный необходимый для воспроизведения ситуации код - вы бы получили более точный и быстрый ответ.

Цитата(DenisIV @ Dec 26 2008, 00:14) *
Варнинги достали (>100) sad.gif
Поэтому бороться надо с их причиной, а не следствием.
zltigo
Цитата(Сергей Борщ @ Dec 26 2008, 01:26) *
Это не лирика, это где-то у вас преднамеренно отключены предупреждения (Project->Options->C/C++ compiler->Diagnostics)

Угу, и у тебя тоже smile.gif не все включено, ибо еще, если мне не изменяет склероз, должено быть что-то типа Еxpression is constant.
Цитата(DenisIV @ Dec 26 2008, 00:19) *
while(1) { .... }

Вобще-то сие однозначно со всех точек зрения пишется так:
Код

for(;; )  { .... }
Сергей Борщ
Цитата(zltigo @ Dec 26 2008, 00:50) *
Угу, и у тебя тоже smile.gif не все включено, ибо еще, если мне не изменяет склероз, должено быть что-то типа Еxpression is constant.
Абижяешь, начальник! Я их никогда не отключаю. Нет предупреждения ни в С ни в С++ режиме. ИАР для ARM, 4.30
Цитата(zltigo @ Dec 26 2008, 00:50) *
Вобще-то сие однозначно со всех точек зрения пишется так:
Согласен, так и пишу. Но тут надо было повторить исходные условия эксперимента.
zltigo
Цитата(Сергей Борщ @ Dec 26 2008, 02:15) *
Абижяешь, начальник! Я их никогда не отключаю. Нет предупреждения ни в С ни в С++ режиме.

Я же не говорил про отключение я говорил про "не все включено" smile.gif. Ой, а что у меня это, если написать while(1) :
Код
   IAR ARM ANSI C/C++ Compiler .....
D:\ARM_WORK\COMMON\LPC2000\console.c(356) : Remark[Pe236]: controlling expression is constant

Просто в IAR по умолчанию ремарки отключены sad.gif надо включать, тем более, что под remark в IAR попадают и такие суровые приколы, как
Remark[Pe193]: zero used for undefined preprocessing identifier
XVR
Цитата(Сергей Борщ @ Dec 25 2008, 13:24) *
Не во всех компиляторах. В avr-gcc вызов линкера с опцией --relax приводит к замене пар call/ret на jmp, а jmp (там, где длина перехода позволяет) - на rjmp. Это вполне себе оптимизация и занимается ей именно линкер.
Thnx, не знал, добавлю в копилку beer.gif Но по сравнению с тем, что способен сделать компилятор - это всетаки 'не оптимизация' cool.gif Оптимизации такого уровня способен делать любой компонент в цепочке компиляции, например в Sun'овском ассемблере он мог делать inline подстановки специальных функций (они были описанны в специальных файлах) вместо их вызовов
DenisIV
Цитата(zltigo @ Dec 26 2008, 01:50) *
Вобще-то сие однозначно со всех точек зрения пишется так:
Код
for(;; )  { .... }

А есть разница? smile.gif
Код
while(1) { .... }

По-моему нет.
В справке к Hi-Tech C они предлагают для бесконечного цикла for(;;) { .... }
При каком-то кол-ве циклов внутри цикла for{ for { for { for {}}}}
компилятор вешается поэтому приходится комбинировать for... while... if... и т.д.
В IAR пока не смотрел. Вроде таких проблем не было.
zltigo
Цитата(DenisIV @ Dec 26 2008, 15:42) *
А есть разница? smile.gif

Разумеется. Если for( ; ; ) есть прямое и безусловно однозначное указание компилятору изобразить вечный цикл, то while(1) есть указание крутиться и слушать пока рак на горе свистнет. Что не есть одно и то-же. Хотя сколь-нибудь приличный оптимизирующий компилятор знакомый с русским фольклером и анатомическим строением ракообразных smile.gif тоже сделает безусловный вечный цикл. Ну и, естественно, хороший компилятор при этом обязан предупредить - ты чего тут барин загадки загадываешь? Точно этого хотел, али опосля вчерашнего того.....
Цитата(DenisIV @ Dec 26 2008, 15:42) *
При каком-то кол-ве циклов внутри цикла for{ for { for { for {}}}}
компилятор вешается поэтому приходится комбинировать for... while... if... и т.д.

Опять sad.gif ужасы.
sergeeff
Бьярн Страустрап, 1995 г. Введение в язык С++. Глава 3 Выражения и операторы :

" Странная запись for(;;) - это стандартный способ задать бесконечный цикл; можно произносить это как "навсегда". Это вырожденная форма оператора for; альтернатива - while(1)."
DenisIV
Цитата(zltigo @ Dec 26 2008, 16:39) *
Разумеется. Если for( ; ; ) есть прямое и безусловно однозначное указание компилятору изобразить вечный цикл, то while(1) есть указание крутиться и слушать пока рак на горе свистнет. Что не есть одно и то-же. Хотя сколь-нибудь приличный оптимизирующий компилятор знакомый с русским фольклером и анатомическим строением ракообразных smile.gif тоже сделает безусловный вечный цикл. Ну и, естественно, хороший компилятор при этом обязан предупредить - ты чего тут барин загадки загадываешь? Точно этого хотел, али опосля вчерашнего того.....
Опять sad.gif ужасы.

Ну я бы так не сказал: если в for(;;) нет условия, это может быть ошибкой, а for(;1;) тоже, что и while(1)
и раз уж так, то while() { .... } должно работать так же как и for(;;) ?
Т.е. в for не надо вставлять условие ??? а в while надо ??? Правильным будет всегда с условием. Это точно не противоречит стандарту С. А то, что как вы сказали "оптимизирующий компилятор знакомый с русским фольклором" - это скорее исключение, а не правило. Поэтому и обидно... sad.gif Если я буду всем советовать for(;;) то это не будет правильно. Что for(;;) что while() - Варнинги обеспечены по любому. А хотелось бы писать правильно. И запись for(;1;) будет правильней.
zltigo
Цитата(DenisIV @ Dec 26 2008, 19:26) *
Что for(;;) что while() - Варнинги обеспечены по любому.

smile.gif нет. Для этого просто надо знать язык - по стандарту ВСЕ ТРИ expression у for() ОПЦИОНАЛЬНЫ. В отличии от while() у которого один, но ОБЯЗАТЕЛЬНЫЙ.
При этом оговаривается, что отсутствующее второе выражение у for() заменяется ненулевой константой.
Цитата
А хотелось бы писать правильно. И запись for(;1;) будет правильней.

Не, глупее sad.gif и при этом вменяемый компилятор обязан предупредить, как и в случае с while( 1 ) чем-нибудь типа 'controlling expression is constant'. Кстати, а почему 1, а не 666??? smile.gif глупость, короче, если и писать глупости, то хоть без конкретики - while( TRUE )
sergeeff
Уважаемый гуру! 1 - она и в Африке 1. А что такое TRUE? Макро, которое может и не быть определено или ты забыл подключить нужный .h файл. А если определено, то как 1.

Как написано у Кернигана & Ритчи "Какой цикл выбрать: while или for - это дело вкуса". Нельзя считать, что миллионы программистов, исповедующие другой стиль написания программ, пишут глупости (не скромно это, как-то).
zltigo
Цитата(sergeeff @ Dec 26 2008, 23:02) *
Как написано...

Вы слишком много читаете, настолько много, что смысл прочитанного от Вас ускользает а в памяти остаются только культовые имена. Не найдете Вы в этой классической книге ни одого while( 1 ). А for( ; ; ) найдете, ибо автор 'C' отличался хорошим вкусом. А Ваша читата просто вырвана из другого, не связанного с организацией бесконечных циклов контекста.

Цитата(sergeeff @ Dec 26 2008, 23:02) *
А что такое TRUE?

Общепринятое, максимально читабельное и соответствующее сущности значение.
rezident
А не пора ли уже прекратить "религиозные" споры? Если результат компиляции одинаков, то стилистика пускай на совести программиста останется. Конечно нет пределов совершенству и самосовершенствованию, но и насильно в свою "религию" тоже обращать не стоит. Мнения прозвучали, теперь каждый может сделать выводы. Только уже "молча". Чтобы до размахивания авторитетами и до оскорблений дело не дошло.
HARMHARM
Цитата(XVR @ Dec 26 2008, 10:53) *
...
Оптимизации такого уровня способен делать любой компонент в цепочке компиляции, например в Sun'овском ассемблере он мог делать inline подстановки специальных функций (они были описанны в специальных файлах) вместо их вызовов

Это называется макрос и есть в любом ассемблере, оптимизацией это называть сложно. Тогда уж всё, что позволяет программу писать не прямо в машинных кодах, есть оптимизация smile.gif
zltigo
Цитата(rezident @ Dec 27 2008, 02:34) *
А не пора ли уже прекратить "религиозные" споры? Если результат компиляции одинаков

Результат разный - в случае for( 1 ) приличными компиляторами выдается предупреждение, на которое можно, конечно, наплевать, что сделает компилятор при отключенной оптимизации - тоже на его совести. Можете считать это "религиозным" убеждением, наплевательское отношение к делу, равно, как и безграмотная писанина, мне не по душе. Впрочем в данном случае я смог высказаться полностью, более мне добавить нечего, а далее могущий понять да поймет - продолжать не буду.
XVR
Цитата(HARMHARM @ Dec 27 2008, 02:34) *
Это называется макрос и есть в любом ассемблере, оптимизацией это называть сложно. Тогда уж всё, что позволяет программу писать не прямо в машинных кодах, есть оптимизация smile.gif
Это не есть макрос - он заменяет не макровызов (по ID макроса), а обычную ассемблерную комманду call
rezident
Цитата(zltigo @ Dec 27 2008, 04:51) *
в случае for( 1 ) приличными компиляторами выдается предупреждение, на которое можно, конечно, наплевать, что сделает компилятор при отключенной оптимизации - тоже на его совести.
Хотя я и не имел в виду именно эту конструкцию, но и ее тоже проверил. В последних версиях IAR не выдает ни warning, ни remark ни на while(1), ни на for(;1;) . По-вашему фирма IAR "прогнулась" под привычки программистов? Как-то не соотносится это (желание "прогнуться") с введением той же MISRA C в их компиляторы, не находите?
zltigo
Цитата(rezident @ Dec 28 2008, 01:18) *
В последних версиях IAR не выдает ни warning, ни remark ни на while(1), ни на for(;1;) .

Последние это какие? Ремарки включите.
Код
    573          
    574              for(; 1; )
                            ^
Remark[Pe236]: controlling expression is constant
    575              {
    576                  led_process( led_cnt++ );

Цитата
По-вашему фирма IAR "прогнулась" под привычки программистов? Как-то не соотносится это (желание "прогнуться") с введением той же MISRA C в их компиляторы, не находите?

Не нахожу. MISRA присутствует с незапамятных времен и с "успехом" ругается практически на все smile.gif, что написано. И соответственно доводит до полного абсурда систему варнингов.
rezident
Цитата(zltigo @ Dec 28 2008, 03:38) *
Последние это какие? Ремарки включите
Ремарки включены. Проверил выражения while(1) и for (;1;) на 4-х версиях IAR: EW430 3.30A, EW430 4.10A, EW430 4.11B, EW430 4.20.1. Выдается такая же ремарка, как у вас в примере, но только на версии 3.30A 2005-го года выпуска. На остальных проглатывает без "всхлипов".
zltigo
Цитата(rezident @ Dec 28 2008, 02:16) *
Проверил...

Значит потеряли в 430 ветке. В ARM есть. Причем дело не в "проблеме" банального while( 1 ) а во всех выражениях, где по уже по ошибке получается вечное условие, которе молча тупо и молча sad.gif sad.gif sad.gifвыполняется. Это безусловно не подарок sad.gif И паронаидальная MISRA такого не поймает.
rezident
Цитата(zltigo @ Dec 28 2008, 05:09) *
Значит потеряли в 430 ветке. В ARM есть.
Возникло сомнение. Может я что-то не так делаю? cranky.gif Специально скачал IAR EWARM 5.20.2. Создал новый проект. Включил ремарки везде, где только их встретил в опциях проекта. Но в результате ни на while(1), ни на for (;1;) осуждающих сообщений от компилятора я не получаю. laughing.gif Что я не так делаю?
dch
Цитата(rezident @ Dec 28 2008, 04:23) *
ни на while(1), ни на for (;1;) осуждающих сообщений от компилятора я не получаю.

обыная практика, использовать только ограниченное количество подобных конструкций и при переходе на новый кроскомпилятор их проверить. Все эти девелоперы сейчас не дофинансированы - и поэтому работают некоторые вещи часто не здорово.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.