|
|
  |
фича компиляторв, инкремент переменной |
|
|
|
May 11 2007, 17:48
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(Oldring @ May 11 2007, 18:37)  В выражении ++i + i .... Таки да! Имеет место быть неопределенность исполнения side effect от оператора ++ по отношению к операции сложения. Взгляд замылил префиксный инкремент  , который на самом деле не имеет отношения к делу. Если вернуться к первоисточнику, то в этом конкретном случае ничего принципиально не разрешимого для компилятора нет, однако смягчения правил игры установленные стандартом в виде виде sequence point позволяют ему не разбираться с этими заморочками. Совершенно правильный подход к делу, поскольку заумные выражения усложняет жизнь компилятору и на самом деле ничего не дают програмисту. С другой стороны никто не может запретить разбирать и более сложные конструкции в этом случае он (Watcom, например) спокойно жует и такие перлы и выдает правильное значение 14. Те компиляторы, которые не разбирают - ругаются (IAR). Те компиляторы, которые не разбирают, молчат и выдают произвольное значение - бяки  . Цитата(vromanov @ May 11 2007, 19:08)  Удивительно, что столь очевидная вещь собрала столько сломанных копий. Где Вы копья увидели? А вещь не очевидная, если считать очевидным не использование такой дури в явном виде ни при каких условиях  .
Сообщение отредактировал zltigo - May 11 2007, 18:52
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
May 11 2007, 18:54
|
Участник

Группа: Новичок
Сообщений: 70
Регистрация: 27-03-07
Пользователь №: 26 533

|
Цитата(zltigo @ May 11 2007, 21:48)  Где Вы копья увидели? А вещь не очевидная, если считать очевидным не использование такой дури в явном виде ни при каких условиях  . По всем сообществам разбирают эту строчку. И куча народа дже после правильного ответа продолжают что-то придумывать, строить какие-то предположения.. Еще и колеги на работе по аське достали этим выражением.
|
|
|
|
|
May 11 2007, 19:57
|

Частый гость
 
Группа: Свой
Сообщений: 163
Регистрация: 22-06-06
Из: Киев
Пользователь №: 18 292

|
Цитата(vromanov @ May 11 2007, 20:08)  Удивительно, что столь очевидная вещь собрала столько сломанных копий. Есть кучу куда более прикольных особеностей в с++  //-------------------------------------- Когда-то полдня убил на глюк ИАРА. Код ниже работал в MCС18 (пик), а в ИАРЕ (4.30, ARM) нет. unsigned char c; char* cr; выше инициализация credential; while((c = *credential) != '\r') // Advance until \r (end of credentials) credential++; *credential = '\0'; // NULL char to replace \r. //--------------------------- Пока не заменил на: do { if(*credential=='\r') break; credential++; }while(1); credential++; *credential = '\0'; // NULL char to replace \r. Причем игрался с оптимизациями - не помогало. Вылетало за пределы массивов.
Сообщение отредактировал lebiga - May 11 2007, 20:01
|
|
|
|
|
May 11 2007, 20:02
|
Участник

Группа: Новичок
Сообщений: 70
Регистрация: 27-03-07
Пользователь №: 26 533

|
Цитата(zltigo @ May 11 2007, 23:03)  Никаких придумок - либо компилятор должен выдать 14, либо ссылаясь на биль о правах компиляторов отказаться отвечать на этот вопрос допущения стандарта послать такое выражения подальше. Компилятор ничего не должен.. В стандарте не написано, что он должен посылать такое выражение. Цитата(lebiga @ May 11 2007, 23:57)  //--------------------------------------
Когда-то полдня убил на глюк ИАРА. Код ниже работал в MCС18 (пик), а в ИАРЕ (4.30, ARM) нет. А вот это уже 100% глюк компилятора. Точнее оптимизатора.
|
|
|
|
|
May 11 2007, 20:19
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(vromanov @ May 11 2007, 23:02)  Компилятор ничего не должен.. В стандарте не написано, что он должен посылать такое выражение. Нет, если он взялся разбирать это выражение, то он должен руководствуясь общими правилами выполнения операций и их приоритетов выдать такое значение. А вот отказаться имеет право и в случае отказа естествено не должен ничего и ни кому. Цитата(Oldring @ May 11 2007, 22:59)  IMHO правильное значение может быть 12, 13, но никак не 14.  Выполняется инкремент i, как самый приоритетный (левый или правый на Ваше усмотрение  ) Затем второй инкремент i, потом сложение, как самая неприоритетная операция. Выполнены все три операции в порядке приоритетов. Все.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
May 11 2007, 21:07
|

Гуру
     
Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874

|
Цитата(zltigo @ May 12 2007, 00:19)  Нет, если он взялся разбирать это выражение, то он должен руководствуясь общими правилами выполнения операций и их приоритетов выдать такое значение. А вот отказаться имеет право и в случае отказа естествено не должен ничего и ни кому. http://electronix.ru/forum/index.php?s=&am...st&p=249062Цитата Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message). Это цитата из стандарта. На русский переводить не нужно? Как видите, компилятор никому ничего не должен, все остальное - фантазии. Цитата(zltigo @ May 12 2007, 00:19)  Выполняется инкремент i, как самый приоритетный (левый или правый на Ваше усмотрение  ) Затем второй инкремент i, потом сложение, как самая неприоритетная операция. Выполнены все три операции в порядке приоритетов. Все. Да, именно так. Пусть аргументы '+' вычисляются справа налево  Сначала считывается значение правого i (5) прибавляем 1, записываем значение правого i. Запоминаем результат правого подвыражения (6). Затем считываем значение левого i (6), прибавляем 1, сохраняем новое значение i, запоминаем результат левого подвыражения (7). Теперь к результату правого подвыражения (6) прибавляем результат левого подвыражения (7) и в результате получаем 13. Альтернатива - когда результаты преинкремента прописываются в переменные в конце вычисления выражения (имеют право - точка сохранения результатов однозначно не определена). В этом случае результат двух подвыражений будет 6, и их сумма будет 12. А вот как получить 14 - не понимаю
--------------------
Пишите в личку.
|
|
|
|
|
May 11 2007, 21:57
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(Oldring @ May 12 2007, 00:07)  Это цитата из стандарта. На русский переводить не нужно? Как видите, компилятор никому ничего не должен, все остальное - фантазии. Переводить не нужно. Может вам мой предыдущий пост на английский перевести? Или постараетесь мой русский язык понять? Повторять не вижу смысла. Цитата Запоминаем результат правого подвыражения (6) Вот 'запоминаем' это и есть чистейшей воды фантазии. С какого бодуна компилятор будет заводить промежуточную переменную-дубль для запоминания? Только если у него совсем крышу снесло. Цитата Альтернатива - когда результаты преинкремента прописываются в переменные в конце вычисления выражения (имеют право - точка сохранения результатов однозначно не определена). В этом случае результат двух подвыражений будет 6, и их сумма будет 12. Это или инкремент суммирование инкремент суммы с тем-же результатом - имеет право, только если это он сделает без warnig я не пойму такой поступок. Цитата А вот как получить 14 - не понимаю  Тогда перечитайте, вдруг поймете. Если не поймете - можете поискать компилятор, который без warning выдаст результат отличный от 14. Может удастся принять, как даденность  . Вдруг найдете - сообщите, что-бы вдруг я случайно не стал пользовать небрежно писанный компилятор.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
May 12 2007, 07:23
|

Гуру
     
Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874

|
Цитата(zltigo @ May 12 2007, 01:57)  Переводить не нужно. Может вам мой предыдущий пост на английский перевести? Или постараетесь мой русский язык понять? Повторять не вижу смысла. А что - переведите, будет любопытно.  Вот только это все равно будет Ваше личное мнение, пусть и на английском языке, в отличие от процитированных мною требований стандарта. Цитата(zltigo @ May 12 2007, 01:57)  Вот 'запоминаем' это и есть чистейшей воды фантазии. С какого бодуна компилятор будет заводить промежуточную переменную-дубль для запоминания? Только если у него совсем крышу снесло. По правилам формальной семантики выражений языка С (так как мы говорим о "правильности" выражений - мы на время забываем, что такое выражение в целом - undefined bihavior). '+' суммирует результаты своих левого и правого подвыражений. С какого бодуна результат первого подвыражения изменяется после его вычисления? Цитата(zltigo @ May 12 2007, 01:57)  Тогда перечитайте, вдруг поймете. Если не поймете - можете поискать компилятор, который без warning выдаст результат отличный от 14. Может удастся принять, как даденность  . Вдруг найдете - сообщите, что-бы вдруг я случайно не стал пользовать небрежно писанный компилятор. Я-то как раз понимаю, как компилятор получает такой результат. У многих компиляторов один из промежуточных этапов компиляции - получение трехадресного кода. При этом разработчики компиляторов, помня правило, процитированное мною первым в первом моем посте, полагаются на то, что переменная i второй раз в одном и том же выражении не изменится, и в ней можно сохранить промежуточный результат подвыражения вместо заведения еще одной промежуточной переменной. Такое предположение компилятора в данном случае является ошибочным. То есть такое поведение - побочный эффект, допускаемый стандартом как undefined bihavior, но никак не "правильное" поведение компилятора.  P.S. Что касается "небрежно написанных компиляторов" - есть такая русская пословица, про зеркало. Компилятор может выдавать что угодно в подобных выражениях. Делать или нет специальный анализ выражения для генерации предупреждений в таких случаях - это выбор разработчиков компиляторов, тем более, что во многих случаях (с указателями) компилятор просто не может знать, что два подвыражения модифицируют один объект. Поэтому лучше так не пишите, а если пишите - то ничего не требуйте от компилятора. Язык С, действительно, налагает довольно высокие требования на квалификацию программиста в части неиспользования некоторых конструкций.
--------------------
Пишите в личку.
|
|
|
|
|
May 12 2007, 08:31
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(Oldring @ May 12 2007, 10:23)  Я-то как раз понимаю, как компилятор получает такой результат.... Я тоже. Только это внутреннее дело компилятора, как он обрабатывает неправильные с точки зрения стандарта (определяющего минимальные требования к компилятору) конструкции. То, что k=++i + ++i; компилятор имеет право не заморачиваясь на специальные анализы тупо на автомате разбирать и получать непредсказуемый результат это понятно. И никто никогда против этого не возражал. То, что разработчики компиляторов имеют право не прикрываясь минимальными требования стандарта разбирать более сложные выражения, надеюсь не вызывает Вашего категорического непрятия? Впрочем, если и вызывает, то пожалуй с этим разработчики компиляторов могут не согласиться  . Выражение k=++i + ++i; являсь совершенно диким, тем не менее поддается однозначной разборке согласно основополагающим правилам операций и их приоритетов. Про трудности компиляции такого и _правильное_ решение стандарта разрешить не заморачиваться с такой разборкой все ясно. Цитата Что касается "небрежно написанных компиляторов" - есть такая русская пословица, про зеркало. Это не ко мне. Я не писал, не пишу и не буду писать подобных выражений, но тем не менее, если вдруг комилятор позволит себе не выдав предупреждение в таком выражении выдать значение отличное от 14, то это меня насторожит и приведет к некоторому недоверию к такому компилятору, поскольку он чего-то не поняв позволил себе меня не предупредить. Цитата Делать или нет специальный анализ выражения для генерации предупреждений в таких случаях - это выбор разработчиков компиляторов Это их право. Только у меня тоже есть право  не использовать такие компиляторы  . Поскольку сегодня выходной день, то я провел маленький тест используемых мною в повседневной жизни компиляторов. OpenWatcom, GCC, Borland не возразили и выдали правильный результат. IAR, VisualDSP - выдали предупреждение. Все это с учетом того, что warnigs я всегда по максимуму активизирую и без оптимизации компиляцию не пользую. Результат меня полностью удовлетворил - по поводу разборки этой дури у меня претензий к используемым мною компиляторам нет и с их разработчиками у меня коннсенсус  . Цитата Поэтому лучше так не пишите, а если пишете - то ничего не требуйте от компилятора. К чему это адресное обращение? Я призывал так писать??? P.S. Пожалуй по четвертому кругу я больше не пойду изъясняться по проблемам k=++i + ++i;
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
May 12 2007, 08:45
|

Гуру
     
Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874

|
Цитата(zltigo @ May 12 2007, 12:31)  Выражение k=++i + ++i; являсь совершенно диким, тем не менее поддается однозначной разборке согласно основополагающим правилам операций и их приоритетов. Про трудности компиляции такого и _правильное_ решение стандарта разрешить не заморачиваться с такой разборкой все ясно. Ну так приведите свой правильный разбор. Я свой привел, приводящий к 12 или 13. Я утверждаю, что 14 - это неправильный результат исходя из семантики операций. Цитата(zltigo @ May 12 2007, 12:31)  К чему это адресное обращение? Я призывал так писать??? В ответ на Ваше утверждение, что для Вас имеет принципиальное значение, какой результат выдается для этого выражения. Если я Вас неправильно понял - тогда извините.
--------------------
Пишите в личку.
|
|
|
|
|
May 12 2007, 09:26
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(Oldring @ May 12 2007, 11:45)  Ну так приведите свой правильный разбор. Я приводил. Цитата Я свой привел, приводящий к 12 или 13. Приводили, но не с точки зрения базовых правил а с точки зрения как может быть построена разборка выражения в потрохах компилятора. Что позволяет объяснить, почему появляется неправильный результат и почему стандарт не требует разбирать такую ерунду. Но все это не имеет отношения к пользователю компилятора написавшего дурацкое, сложно разбираемое компилятором (если он за это возьмется!), хреново оптимизируемое и трудно понимаемое человеком, но вполне однозначо трактуемое выражение - "берем одну едиственную переменную, инкрементируем один раз, инкрементируем второй раз, прибавляем к ней ее-же значение. Цитата В ответ на Ваше утверждение, что для Вас имеет принципиальное значение, какой результат выдается для этого выражения. Если я Вас неправильно понял - тогда извините. Про "принципиальное значение" я ни сном ни духом не поминал. Повторяю - выдаваемый результат лично для меня имеет некоторое (а отнюдь не принципиальное) значение только в плане оценки компилятора и только в том единственном случае, когда он не выдав предупреждения выдал результат отличный от 14. В проведенных тестах я даже не смотрел на результат у компиляторов которые выдали warning-и. Во настолько он для меня имеет "принципиальное значение"  Извиняю.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
  |
4 чел. читают эту тему (гостей: 4, скрытых пользователей: 0)
Пользователей: 0
|
|
|