Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: фича компиляторв
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Страницы: 1, 2
zltigo
Цитата(Oldring @ May 12 2007, 18:14) *
Как истолковать? Как невыдачу предупреждения на undefined bihavior код. biggrin.gif

И при этом выдачу предупреждения при компиляции компилятором из этой-же линейки для другой платформы smile.gif??? И выдачу предупреждения undefined bihavior этим-же компилятром для другого выражения? И все это с грубыми, по Вашему мнению нарушениями?
Цитата
Компилятор - не такая уж непостижимая для понимания программа.

Компилятор вполне постижимая - сам писал в свое время со своего-же тестового языка smile.gif для Z80 target. Проблема здесь в толковании правил и обеспечении соблюдения неписанных договоренностей.
Oldring
Цитата(zltigo @ May 12 2007, 19:42) *
И при этом выдачу предупреждения при компиляции компилятором из этой-же линейки для другой платформы smile.gif??? И выдачу предупреждения undefined bihavior этим-же компилятром для другого выражения? И все это с грубыми, по Вашему мнению нарушениями?

Компилятор вполне постижимая - сам писал в свое время со своего-же тестового языка smile.gif для Z80 target. Проблема здесь в толковании правил и обеспечении соблюдения неписанных договоренностей.


Я считаю, что все, что касается правил компиляции - изложено в стандарте языка. Там нет ничего непостижимого. Стандарт - это закон. Поэтому доводы "это непостижимо" не приемлю, извините.

Я Вам привел цитаты из стандарта и разъяснил, как именно значение 14 противоречит понятию "правильности" результата этого выражения если даже забыть на время об ограничении по поводу undefined bihavior для выражения в целом. Вы можете привести какие-либо аргументы в поддержку своей позиции (утверждений об "однозначности разбора" и о "правильности" результата 14) кроме того, что некоторые космпиляторы не выдают предупреждение, выдавая в результате 14?

Ну и кроме того, хочу привести последний аргумент. То, что часть компиляторов выдает 13 (имеют полное право), а часть - 14, не означает ли, что компиляторы, не выдающие на такой код предупреждение, просто имеют более слабую диагностику по сравнению с теми, которые выдают такую диагностику?
zltigo
Цитата(Oldring @ May 12 2007, 19:06) *
Стандарт - это закон. Поэтому доводы "это непостижимо" не приемлю, извините.

Закон. Только закон (хоть "компиляторный" хоть "человеческий" ) все не описывает и уж точно не все описывает понятно. Отсюда и профессиональные писатели компиляторов и профессиональные адвокаты. И уж тем более закон не запрещает разбирать компиляторам более сложные случаи. Вот и получаем, те которые разбирают и не жалуются на непонятливость те выдают 14.
Цитата
Ну и кроме того, хочу привести последний аргумент.

Это хорошо-бы smile.gif а то ходим уже по мамнадцатому кругу sad.gif
Цитата
То, что часть компиляторов выдает 13 (имеют полное право), а часть - 14, не означает ли, что компиляторы, не выдающие на такой код предупреждение, просто имеют более слабую диагностику по сравнению с теми, которые выдают такую диагностику?

Может и быть, но! Повторяю неудобные вопросы на которые нет ответов:
B при этом, те которые 14 - все как один не выдают warnings, а те которые 13 все напротив - выдают. Случайность?
Компилятор одной линейки для одной платформы без warnings выдает 14 а для другой с warnings и 13.
Случайность?
Поведение с 14 позволяют себе минимум 4 весьма распространенных компилятора. Случайнось?
Не слишком-ли много неумелых толкователей закона среди писателей компиляторов?

P.S.
Пат.
Oldring
Цитата(zltigo @ May 12 2007, 20:29) *
Закон. Только закон (хоть "компиляторный" хоть "человеческий" ) все не описывает и уж точно не все описывает понятно. Отсюда и профессиональные писатели компиляторов и профессиональные адвокаты.


Мне-то в этом законе все совершенно понятно. Это Вы почему-то жалуетесь, что там что-то непонятно написано. А по-моему, все совершенно четко. Логика есть логика. cool.gif

Кстати, Вы так и не показали, как аккуратно исполняя дерево грамматического разбора обсуждаемого выражения можно получить 14. biggrin.gif

Цитата(zltigo @ May 12 2007, 20:29) *
Может и быть, но! Повторяю неудобные вопросы на которые нет ответов:
B при этом, те которые 14 - все как один не выдают warnings, а те которые 13 все напротив - выдают. Случайность?
Компилятор одной линейки для одной платформы без warnings выдает 14 а для другой с warnings и 13.
Случайность?
Поведение с 14 позволяют себе минимум 4 весьма распространенных компилятора. Случайнось?
Не слишком-ли много неумелых толкователей закона среди писателей компиляторов?

P.S.
Пат.


arm-alf-gcc с опциями по умолчанию тоже никаких предупреждений не выдает, компилируя в 13. Нужно продолжать опровержения Вашего утверждения про заговор писателей компиляторов?

P.S. Это не пат, это мат. biggrin.gif
zltigo
Цитата(Oldring @ May 12 2007, 19:57) *
arm-alf-gcc с опциями по умолчанию тоже никаких предупреждений не выдает,

Меня не интересует работа компиляторов с подавленными warnings, даже если они собраны кем-то по умолчанию.
Цитата
Нужно продолжать опровержения Вашего утверждения про заговор писателей компиляторов?

Нет, по причине того, что Вы уже многократно однообразно повторяетесь. Не отвечая на встречные вопросы.
Если что-то новенькое - пишите всенепременнейше!
Цитата
P.S. Это не пат, это мат. biggrin.gif

Можете про себя считать, как угодно. Я это переживу smile.gif.
singlskv
Я Вам не помешаю ? smile.gif
Выскажу свое ИМХО:
- Компилятор который не выдет warning в такой ситуации, вне зависимости от уровня оптимизации,
это компилятор который не следует стандарту С.
- соглашусь с Oldring, 12 или 13 еще как-то укладывается в то, как учитывая стандарт С,
компилятор должен был бы разбирать это выражение
- результат 14 для большинства компиляторов говорит только о том,
что "очень хотелось соптимизировать" и компилятор "успешно" справился с этой
задачей...
2zligo
Если Вы имеете в виду такую предсказуемость работы "оптимизаторов" в компиляторах,
то с Вами я тоже полностью согласен smile.gif
zltigo
Цитата(singlskv @ May 13 2007, 01:53) *
- результат 14 для большинства компиляторов говорит только о том,
что "очень хотелось соптимизировать" и компилятор "успешно" справился с этой
задачей...

Нет этим однозначно объяснить не получается. Посмотоите результаты реального OpenWatcom, три из многочисленных вариантов (от полной заоптимизированности в банальный возврат 14, до тупого кода при полностью отключенной оптимизации) приводил выше - без разницы. Последовательность действий при этом совершенно не изменялась - решене было приято уже ДО оптимизатора.
Oldring
Цитата(zltigo @ May 12 2007, 21:55) *
Меня не интересует работа компиляторов с подавленными warnings, даже если они собраны кем-то по умолчанию.


А с отсутствующими - интересует smile.gif

Цитата(zltigo @ May 12 2007, 21:55) *
Нет, по причине того, что Вы уже многократно однообразно повторяетесь. Не отвечая на встречные вопросы.
Если что-то новенькое - пишите всенепременнейше!


Что-то новенькое?
По поводу "часть компиляторов выдает ворнинги, а часть нет" - отвечать не могу в принципе. Не понимаю логику вопроса. Я почему-то в ходе этого спора вспомнил нумерологию. Я ведь тоже не могу опровергнуть утверждение про несчастливость числа 13.

Других встречных вопросов не видел.

Ключевой метод для признания "правильности" вычисления выражения - вычисление выражения по грамматическому дереву в соответствии с семантическими правилами. Операция за операцией. Чтобы получить 14 нужно обязательно рассматривать результат ++i как lvalue. По крайней мере, в ANSI C-99 он не lvalue, следовательно, число 14 не может претендовать на правильность. Вы почему-то это ключевое логическое утверждение проигнорировали.

Цитата(zltigo @ May 12 2007, 21:55) *
Можете про себя считать, как угодно. Я это переживу smile.gif.


Это здорово. Не обижайтесь - мне само выражение понравилось. Ничего личного.

Цитата(zltigo @ May 13 2007, 10:48) *
Нет этим однозначно объяснить не получается. Посмотоите результаты реального OpenWatcom, три из многочисленных вариантов (от полной заоптимизированности в банальный возврат 14, до тупого кода при полностью отключенной оптимизации) приводил выше - без разницы. Последовательность действий при этом совершенно не изменялась - решене было приято уже ДО оптимизатора.


Я совершенноуже запутался в версиях компиляторов, на которые Вы ссылались.

Замечу только, что действия по оптимизации могут предприниматься и без оптимизатора - на этапе порождения внутреннего представления по грамматическому дереву, или на этапе кодогенерации. Как попытка использовать систему команд процессора эффективно.

Ключевое отличие x86 от ARM - именно в системе команд. в ARM нет операций АЛУ с аргументами в памяти. В системе команд x86 таких операций море, причем, они широко используются для обхода затычки с регистрами. Поэтому на x86 выгоднее рассматривать результат ++i как находящийся в самой ячейке памяти переменной i, хоть он и не lvalue, потому что ошибка может возникнуть только в выражениях с undefined bihavior.

Кстати, если определить i как volatile - в gcc для x86 результат становится 13.
scifi
Ну вы даёте... Эту бы энергию - да в мирных целях :-)
Кстати, тут ссылки на стандарт языка Си. А где его взять можно? Причём и C90, и C99? Посмотрел в закромах - не нашёл...
zltigo
Цитата(Oldring @ May 13 2007, 11:35) *
А с отсутствующими - интересует smile.gif

Да ТОЛЬКО с отсутствующими и интересует. К тем которые предупредили - претензий и спроса нет.
Цитата
Других встречных вопросов не видел.

Пост номер 53. Это не вопросы, на которые я "требую" ответа. Это вопросы, которые я прежде всего задал себе и сам не знаю (не знал на тот момент) на них ответа. Но отсутствия ответа на них не позволяет мне прятать голову в песок и обвинять компиляторы не выдавшие warning в кривости.
Цитата
Я совершенноуже запутался в версиях компиляторов, на которые Вы ссылались.

Странно. 4 компилятора не выдающие warning? но выдающие 14 были перечислены рядышком в одной cтроке.
Цитата
Кстати, если определить i как volatile - в gcc для x86 результат становится 13.

Хороший эксперимент!
Кроме того, когда я экспериментировал с GNU, я по ленности запихнул эти строчки в готовый поюсовый проект sad.gif. Теперь повторив c сишным компилятором удалось получить warning. GCC x86 покинул ряды защитников "14":). С плюсовыи GNU странности, ну да бог с ним - уже не до этого. Нашел время спытать и Borland - он покидает арену с позором - выдает произвольные значения и никаких warning.
Microsoft-а у меня не стоит и лично не пытал. Посему на даный момент остается единственный достоверный стойкий оловянный солдатик - OpenWatcom. Всегда (в том числе и с volatile) выдающий 14.
Что уже явно может быть исключительно личным мнением разработчиков одного компилятора.
Oldring
Цитата(zltigo @ May 13 2007, 10:24) *
Посему на даный момент остается единственный достоверный стойкий оловянный солдатик - OpenWatcom. Всегда (в том числе и с volatile) выдающий 14.


А вот это явный глюк компилятор. Посмотрите в ассемблере - cколько он раз считывает значение переменной i.
zltigo
Цитата(Oldring @ May 13 2007, 09:43) *
А вот это явный глюк компилятор. Посмотрите в ассемблере - cколько он раз считывает значение переменной i.

Никаких глюков. Считывается один раз. В случае оптимизации - все дальнейшее происходит в регистрах. В абсолютно неоптимизированном варианте - заводится дубль переменной и уже с ним дальнейшие операции. Промежуточные варианты благодаря развитой работой с памятью тоже возможны.
Oldring
Цитата(zltigo @ May 13 2007, 11:24) *
Никаких глюков. Считывается один раз. В случае оптимизации - все дальнейшее происходит в регистрах. В абсолютно неоптимизированном варианте - заводится дубль переменной и уже с ним дальнейшие операции. Промежуточные варианты благодаря развитой работой с памятью тоже возможны.


Один раз, а не два? В случае volatile int i?
А если просто написать x = i + i?
zltigo
Цитата(Oldring @ May 13 2007, 11:02) *
Один раз, а не два? В случае volatile int i?
А если просто написать x = i + i?

Не два. Зачем два? Один раз в РЕГИСТР. Затем операции с регистром или тот-же регистр в промежуточную память и операции с промежуточной памятью. Какие проблемы?
Oldring
Цитата(zltigo @ May 13 2007, 12:11) *
Не два. Зачем два? Один раз в РЕГИСТР. Затем операции с регистром или тот-же регистр в промежуточную память и операции с промежуточной памятью. Какие проблемы?


Проблемы с volatile. Чтение volatile переменной может обладать побочными эффектами, неизвестными компилятору, как и запись. Поэтому компилятор не может по своей воле оптимизировать чтение volatile переменных.
zltigo
Цитата(Oldring @ May 13 2007, 11:19) *
Проблемы с volatile. Чтение volatile переменной может обладать побочными эффектами, неизвестными компилятору, как и запись.

Ну с этим все очень просто. Берем Help к компилятору и читаем, что нам обещано:
Код
An object may be declared with the keyword  volatile.  Such an object may be freely modified by the program, and its value also may be modified through actions outside the program.

Про побочные эффекты, при чтениии это не забота volatile. Характеристика обьекта с модификатором volatile описана четко. Все остальное фантазии и пустые надежды на решение всех проблем одним махом.
Цитата
Поэтому компилятор не может по своей воле оптимизировать чтение volatile переменных.

Может, с осторожностью:
Код
The keyword  volatile indicates to the compiler that care must be taken when optimizing code referring to the object, so that the meaning of the program is not altered.  An object that the compiler might otherwise have been able to keep in a register for an extended period of time will be forced to reside in normal storage so that an external change to it will be reflected in the program's behavior.

Если вдруг существуют компиляторы налагающие более суровые ограниченя, не сочтите за труд назвать их. Очень полезно для общего развития.
Oldring
Цитата(zltigo @ May 13 2007, 13:15) *
Может, с осторожностью:
...


Компилятор - GCC.

Не сочтите за труд, прочтите, в конце концов, стандарт языка, или хотя-бы нормальный учебник по языку программирования. Главное назначение volatile - работа с аппаратными регистрами. Например, получение данных из аппаратного FIFO. Изменение количества чтений из такой ячейки памяти приведет к некорректной работе программы. Поэтому атрибут volatile налагает очень жесткие ограничения на любой компилятор: каждое чтение volatile объекта является внешним эффектом программы, поэтому никакая оптимизация не имеет права изменить количество таких чтений.

Даже удивительно, что мне приходится Вам излагать настолько базовые понятия.

P.S. Убедитесь, пожалуйста, что Watcom поддерживает ANSI C, а не остановился в своем развитии на K&R C.
zltigo
Цитата(Oldring @ May 13 2007, 12:27) *
Не сочтите за труд, прочтите, в конце концов, стандарт языка

Может я чего пропустил? Тогда пожалуйста сюда ссылочку из стандарта про главню задачу volatile:
Цитата
Главное назначение volatile - работа с аппаратными регистрами. Например, получение данных из аппаратного FIFO


Цитата
Даже удивительно, что мне приходится Вам излагать настолько базовые понятия.

Удивительно другое, что Вы полагаете, что для решения описанных проблем достаточно volatile sad.gif
Цитата
P.S. Убедитесь, пожалуйста, что Watcom поддерживает ANSI C, а не остановился в своем развитии на K&R C.

OpenWatcom поддерживает С99. А что в K&R упоминается volatile?
Цитата
Поэтому атрибут volatile налагает очень жесткие ограничения на любой компилятор

Накладываемые ограничения:
Цитата
The standards encourage compilers to refrain from optimizations concerning accesses to volatile objects that it might perform on non-volatile objects. The C standard leaves it implementation defined as to what constitutes a volatile access. The C++ standard omits to specify this, except to say that C++ should behave in a similar manner to C with respect to volatiles, where possible. The minimum either standard specifies is that at a sequence point all previous accesses to volatile objects have stabilized and no subsequent accesses have occurred. Thus an implementation is free to reorder and combine volatile accesses which occur between sequence points, but cannot do so for accesses across a sequence point. The use of volatiles does not allow you to violate the restriction on updating objects multiple times within a sequence point.
Oldring
Цитата(zltigo @ May 13 2007, 13:38) *
Может я чего пропустил? Тогда пожалуйста сюда ссылочку из стандарта про главню задачу volatile:
Удивительно другое, что Вы полагаете, что для решения описанных проблем достаточно volatile sad.gif


"Главная задача volatile" описана, безусловно, не в стандарте, а в учебниках по языку. Признаюсь, учебники по языку С я не читал с начала 90-х - но уже в то время все было подробно описано.

В стандарте же написано следующее:

Цитата
An object that has volatile-qualified type may be modified in ways unknown to the
implementation or have other unknown side effects. Therefore any expression referring
to such an object shall be evaluated strictly according to the rules of the abstract machine,
as described in 5.1.2.3.


volatile решает часть задачи работы с аппаратурой, которая касается компилятора. Остальное (например, настройка кеша) касается самой аппаратуры, а не компилятора. Нечего мне приписывать то, что я не писал.

P.S. Есть еще такой документ - "Rationale for International Standard—Programming Languages—C"

Цитата
volatile No cacheing through this lvalue: each operation in the abstract semantics must be
performed (that is, no cacheing assumptions may be made, since the location is not
guaranteed to contain any previous value). In the absence of this qualifier, the
contents of the designated location may be assumed to be unchanged except for
possible aliasing.


Цитата
A static volatile object is an appropriate model for a memory-mapped I/O register.
Implementors of C translators should take into account relevant hardware details on the target
systems when implementing accesses to volatile objects. For instance, the hardware logic of a
system may require that a two-byte memory-mapped register not be accessed with byte operations;
and a compiler for such a system would have to assure that no such instructions were generated,
even if the source code only accesses one byte of the register. Whether read-modify-write
instructions can be used on such device registers must also be considered. Whatever decisions are
adopted on such issues must be documented, as volatile access is implementation-defined. A
volatile object is also an appropriate model for a variable shared among multiple processes.
zltigo
Цитата(Oldring @ May 13 2007, 12:55) *
В стандарте же написано следующее:

Отлично. К первоисточникам припали smile.gif. Ну теперь будучи вооруженным, попробуйте обьяснить, в чем это компилятор провинился:
Цитата
А вот это явный глюк компилятор. Посмотрите в ассемблере - cколько он раз считывает значение переменной i.


Ну и Ваши слова:
Цитата
каждое чтение volatile объекта является внешним эффектом программы, поэтому никакая оптимизация не имеет права изменить количество таких чтений.


Цитата
Нечего мне приписывать то, что я не писал.

Да??? Были перечислены проблемы ображения к "железу" и сказано про volatile. При этом никакие другие средства не упоминались а в реальной жизни для решения этих проблем использования только volatile (без, например, разбиения на sequence points )недостаточно.
Так-что как тогда надо было понимать?

P.S.
Да, и с "удивлением", пожалуйста поокуратнее.
Oldring
Цитата(zltigo @ May 13 2007, 14:12) *
Отлично. К первоисточникам припали smile.gif. Ну теперь будучи вооруженным, попробуйте обьяснить, в чем это компилятор провинился:
Да? Уж больно "удивление" выказано было smile.gif


Да я Вам с самого начала постоянно кидал ссылки на первоисточники - а в ответ получал лишь "жираф большой - ему видней."

Провинился Watcom тем, что абстрактная C машина считывает volatile объект два раза - а код, порождаемый компилятором, содержит одно чтение из объекта. Такая оптимизация нарушает требование стандарта, которое я процитировал в предыдущем посте.

Кстати. Вы дописали в конце цитату утверждения, что компилятор имеет право комбинировать volatile обращения между соседними sequence point. Так вот, это явный бред. Вы не привели ссылку на источник цитаты - гугл в качестве источника дает документацию на GCC. Это утверждение - явная самодеятельсность авторов GCC. Потому что она противоречит приведенной ранее мною цитате из стандарта. Переупорядочивание обращений к этому не относится. А вот комбинирование может привести к тому, что побочные эффекты от обращения будут потеряны, вместо того, чтобы быть завершены к следующей sequence point.
zltigo
Цитата(Oldring @ May 13 2007, 13:26) *
Провинился Watcom тем, что абстрактная C машина считывает volatile объект два раза - а код, порождаемый компилятором, содержит одно чтение из объекта. Такая оптимизация нарушает требование стандарта, которое я процитировал в предыдущем посте.


Цитата
..компилятор имеет право комбинировать volatile обращения между соседними sequence point. Так вот, это явный бред. Это утверждение - явная самодеятельсность авторов GCC. Потому что она противоречит приведенной ранее мною цитате из стандарта.


Ну как-бы я все понял и осознал - существует только одно правильное толкование "стандарта" и оно принадлежит Oldring.
Aвторы компиляторов дружно "отдыхают", ну а остальные фоне этого вообще никто и звать их никак.
Oldring
Цитата(zltigo @ May 13 2007, 14:37) *
Aвторы компиляторов дружно "отдыхают", ну а остальные фоне этого вообще никто и звать их никак.


Я и говорю: "жираф большой - ему видней".
Ладно. Продолжать мне скушно.
Адью.
vromanov
Цитата(zltigo @ May 13 2007, 14:37) *
Ну как-бы я все понял и осознал - существует только одно правильное толкование "стандарта" и оно принадлежит Oldring.
Aвторы компиляторов дружно "отдыхают", ну а остальные фоне этого вообще никто и звать их никак.

Вообще то известно, что авторы компиляторво делают ошибки в полный рост. Для этого достаточно почитать этот форум.
Ну а то что в этом случае i не надо читать два раза очень удивительно слышать от человека, который занимается разработкой для микропроцессоров. Тут таких случаев навалом.
То что это не так в ваткоме говорит о том, что этот компилятор практически не используется для написания совты связанного с работой с железом и такие ошибки не ВЫЛЕЗЛИ у пользователей.
zltigo
Цитата(vromanov @ May 13 2007, 15:03) *
Вообще то известно, что авторы компиляторво делают ошибки в полный рост.

Удивительно другое, что volatile-"правильный" компилятор пока найти не удалось smile.gif.
Цитата
Ну а то что в этом случае i не надо читать два раза очень удивительно слышать от человека, который занимается разработкой для микропроцессоров.

Человек, "который занимается" умеет четко выражать свои мысли посредством vоlatile и разбиения инструкций на sequence point. При этом меня абсолютно устраивает минимально-необходимо-достаточная трактовка volatile присутствующая во всех известных мне компиляторах и процитированная ранее по Watcom-овскому хелпу и документации к GCC. При этом такая трактовка volatile не отметает оптимизацию на корню.
Цитата
То что это не так в ваткоме говорит о том, что этот компилятор практически не используется для написания совты связанного с работой с железом и такие ошибки не ВЫЛЕЗЛИ у пользователей.

Ну то, что я использую под 186 и не только, и то, что IBM-PC это тоже железо - забудем? Но что делать с GCC там ведь вообще "явный бред":
Код
The standards encourage compilers to refrain from optimizations concerning accesses to volatile objects that it might perform on non-volatile objects. The C standard leaves it implementation defined as to what constitutes a volatile access. The C++ standard omits to specify this, except to say that C++ should behave in a similar manner to C with respect to volatiles, where possible. The minimum either standard specifies is that at a sequence point all previous accesses to volatile objects have stabilized and no subsequent accesses have occurred. Thus an implementation is free to reorder and combine volatile accesses which occur between sequence points, but cannot do so for accesses across a sequence point. The use of volatiles does not allow you to violate the restriction on updating objects multiple times within a sequence point.

Так вот, я с этим "бредом" полностью согласен. Нормальная, сбалансированная реализация. Не вырубающая оптимизацию полностью при обращении к Random Access (RAM в том числе) обьектам. "Проблемы" c, например, FIFO должны решаться явным образом разбиением обращений на sequence point. Обращение к FIFO (кстати, как там дела c существованием FIFO в "абстрактной С машине" поминаемй с стандарте дела обстоят? ) не должно висеть тяжким грузом на всем остальном.
PrSt
Цитата(Oldring @ May 11 2007, 22:59) *
Почему 14?
IMHO правильное значение может быть 12, 13, но никак не 14. biggrin.gif

аналогично!
почему 14 ???
13 и баста...
вариант с 12 - доспустим,но это добжен быть невероятно глупый компилятор, причем с патароченными критериями и правилами оптимизации...

но а 14 откуда берется?
и почему у gcc тоже 14???

я прошу, нет, ... требую... объясните плз...

я конечно не виликий гуру - но тут то заблудиться трудно!
13 и ничего иного...
x = ++i+ ++i

разбиваем как это делает компилятор
temp1 = ++i (стало 6)
temp2 = ++i (стало 7)
x=temp1+temp2 (стало 13)

от куда 14???

...и вообще! что это у людей за безгранично глупая привычка все писать без скобок !?
что за мода надеяться на безграничный интелект компилятора?
...истинну глаголю - индусы писали это эйфелеву конструкцию!
не иначе ...или [CENSORED]!

а глупость то видать явно в компиляторах и это напоминает подвох с x=2+2*2, чему равен x?

.
lebiga
Пора рассматривать известную шутку Ричи и Кернигана

for(;P('\n'),R-;P('|'))for(e=C;e-;P('_'+(*u++/8)%2))P('| '+(*u/4)%2);

Вдруг и это вызовет полемику? smile.gif
zhevak
Цитата
...
разбиваем как это делает компилятор
temp1 = ++i (стало 6)
temp2 = ++i (стало 7)
x=temp1+temp2 (стало 13)

от куда 14???
...


1. Да простит меня великий All, что я поднял эту волну... Просто мною овладело любопытство.

2. Я про явное отличие компиляторов С/С++ и С# скажу. Точнее скажу свои доводы, как эти компиляторы понимают код
x = ++i + ++i;

Компиляторы С/С++ складывают (последняя операция -- сложение) переменную i c переменной i, в то время как C# складывае результат выражения ++i с результатом выражения ++i.

Таким образом, для С/С++ на момент сложения переменных, они будут равны 7 (даром, что это одна и та же переменная!), результат получаем -- 14. C# складывает результаты выражений: первый результат на момент сложения равен 6, второй -- 7, что в итоге дает 13.

Отсюда вопрос -- что должны складывать компиляторы: результаты выражений или значения переменных?

Меня интересует, как так получилось, что возникла такая вольность интерпретации этого злого выражения у компиляторов. Вольность -- это потенциальная опасность переноса кода с одного компайлера на другой. Вот что меня беспокоит.

И еще, наверно стоит зайти на РСДН, посмотреть что там говорят гуру. (Сылку я приводил в первом посте.)
vromanov
А то, что значение переменной может поменяться в результате прерывания? Или в начале каждой sequence point прерывание запрещать, а потом разрешать?
zhevak
Цитата(vromanov @ May 14 2007, 06:07) *
А то, что значение переменной может поменяться в результате прерывания? Или в начале каждой sequence point прерывание запрещать, а потом разрешать?

не-е, ну... предполагается, что переменная i -- это обычная переменная, не volatile. Определена внутри какой-нибудь функции, т.е. размещается либо на стеке, либо в регистрах МП. Иначе говоря, никто из вне ее торкнуть не может.
vromanov
Цитата(zhevak @ May 14 2007, 04:19) *
не-е, ну... предполагается, что переменная i -- это обычная переменная, не volatile.

Про исходный пример все ясно. Так просто нельзя писать, т.к. результат по стандарту не определен. Мы уже про другое.
Oldring
Цитата(zhevak @ May 14 2007, 04:04) *
Отсюда вопрос -- что должны складывать компиляторы: результаты выражений или значения переменных?

Меня интересует, как так получилось, что возникла такая вольность интерпретации этого злого выражения у компиляторов. Вольность -- это потенциальная опасность переноса кода с одного компайлера на другой. Вот что меня беспокоит.


Если следовать строго правилам стандарта, отличие может возникнуть только в том случае, если переменная i объявлена как volatile. В этом случае можно сказать однозначно: так как результат ++i по стандарту не является lvalue, компилятор не имеет права считывать i второй раз и должен использовать результат вычисления выражения.

Если же i не volatile - то в корректно написанных выражениях нет никакой разницы, что использует компилятор. Но исходное выражение нарушает требования к корректным выражениям с однозначным результатом. Таких неоднозначностей в языке С довольно много, они неизбежны в столь низкоуровневом языке и переречислены в стандарте языка. Если компилятор достуточно наворочен - он в части таких случаев может выдать предупреждение.
amw
В пост #4 при компилляции добавляем -Wall и получаем warning и значение 14.
Напомню, это в GCC 3.4.5 x86
cebotor
Цитата(singlskv @ May 13 2007, 02:53) *
Я Вам не помешаю ? smile.gif
Выскажу свое ИМХО:
- Компилятор который не выдет warning в такой ситуации, вне зависимости от уровня оптимизации,
это компилятор который не следует стандарту С.
- соглашусь с Oldring, 12 или 13 еще как-то укладывается в то, как учитывая стандарт С,
компилятор должен был бы разбирать это выражение
- результат 14 для большинства компиляторов говорит только о том,
что "очень хотелось соптимизировать" и компилятор "успешно" справился с этой
задачей...
2zligo
Если Вы имеете в виду такую предсказуемость работы "оптимизаторов" в компиляторах,
то с Вами я тоже полностью согласен smile.gif

все операции детерминированы . в выражении ++i + ++i во втором "отделении спектакля"
производиться только сложение двух подвыражений - а подвыражения эти - равны текущему значению i (вариант а), либо вычисленному значению подвыражения (вариант б). нигде не написано в стандарте про то какой вариант является правильным - именно поэтому это и называется undefined behavior. неправ тот компилятор который не показал ворнинг - а число при этом можно выдавать где то от 12-ти до 14-ти smile.gif
Oldring
Цитата(cebotor @ May 15 2007, 10:19) *
все операции детерминированы . в выражении ++i + ++i во втором "отделении спектакля"
производиться только сложение двух подвыражений - а подвыражения эти - равны текущему значению i (вариант а), либо вычисленному значению подвыражения (вариант б). нигде не написано в стандарте про то какой вариант является правильным - именно поэтому это и называется undefined behavior. неправ тот компилятор который не показал ворнинг - а число при этом можно выдавать где то от 12-ти до 14-ти smile.gif


Еще раз.

Результат всего выражения компилятор имеет право выдать любой - хоть -666, потому что undefined behavior.

Но интерпретация значения выражения ++i прописана в стандарте совершенно четко. Результат не является lvalue. Следовательно, это не есть значение переменной i, а именно вычисленное значение подвыражения. В корректных выражениях различие можно обнаружить только если i - volatile.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.