>а кнонть уже попробовал пересобрать gcc-4 самим gcc-4? Соберется ли ? :-)
AFAIK он так и собирается! Сначала сторонним компилятором, потом собой, потом тем что получилось после сборки собой. Потом сравнивает результаты (сборки собой не должны отличаться).
2vada: а что, стандарт С не предусматривает, какая операция должна первой выполниться? Поведение компилятора должно быть четко, *математически* определено в любой ситуации, и такой вот некорректный код наиболее просто описывает "любую ситуацию".
Гарантии, конечно, не дает, но как минимум четко видно, если что-то пошло не так.
> Как кто, разработчики анекдотов конечно, undefined behavior их лучший друг !
Ну почему сразу undefined? с = с не есть lvalue, не так ли? Соответственно, c = c++ выполняется как c = (c++). По крайней мере, с точки зрения формальной логики должно быть 1 :-)
Ставил недавно Debian unstable amd64-gcc4 (собран на каком-то pre). Неделю был полет нормальный. Откатился на amd64-pure64 только из-за неразберих с зависимостями в репозитории. А так - вполне...
>а кнонть уже попробовал пересобрать gcc-4 самим gcc-4? Соберется ли ?
А ты как думаешь ? Его первым делом и собираем им же, 4.0.0 правда я еще не собирал.
>УЧИ МАТЧАСТЬ! c=++c, да один с=с++ НОЛЬ! И НИЧЕГО ДРУГОГО.
Эх, ты! Undefined behaviour, однозначно. Две модификации переменной (= и ++) не разделены точкой следования (присваивание - не является точкой следования). Я даже когда-то где-то ссылку на стандарт C99 давал и подробно объяснял, что и как.
Не читают фундаментальные труды, нет, не читают :)
>>> УЧИ МАТЧАСТЬ! c=++c, да один с=с++ НОЛЬ! И НИЧЕГО ДРУГОГО.
>
>c=++c это:
>{
> c=c+1;
> c=c;
>} итого 1
>
>c=c++ это:
>{
> c=c;
> c=c+1;
>} итого тоже 1 :)
Лопух.
c=c++ :
{
сохраняем c
увеличиваем c на 1
присваиваем c сохран. результат
} итого: 0
Аааа. Только не мой мозг. Сказали же, это UB. Повторяю: UB, unidefined behavior, по слогам не-оп-ре-де-лен-но-е по-ве-де-ние. Все эти выкладки полная и абслютная чушь.
Почему UB? Объясните доступно. Операнды = вычисляются раньше, чем выполняется присваивание. При вычислении левого оператора будет адрес в памяти, правого - число. Их значения не зависят от порядка вычисления. Разве не так?
>>Зачем тебе 4.1? Это же будет эксперементальная ветка?
>С чего ты взял что у них значения номеров версий такое же как у ядра ???
А где ты увидел, что они как у ядра? Они не такие как у ядра. Текущие фиксы осуществляются в свежезарелизиной ветке, а для добавления новых фич открывают новую. Со временем, новая стабилизируется, и ее релизят не изменяя номера. Некоторое время она остается в качестве стабильной ветки и фиксы осуществляются в ней. Потом открывают новую, и т.д. 4.0.1 - будет фикс к 4.0, а 4.1 - пока ее официально не зарелизят (это произойдет никак не в течении месяца), будет экспериментальной.
Никак нет. Все будет зависеть и от компилятора, и от оптимизатора: или постинкремент произойдет _до_ присвоения, или после. UB это. Курить стандарт языка.
> Операнды = вычисляются раньше, чем выполняется присваивание.
да, но это здесь не причем. в стандарте сказано, что ++ будет вычесленно
в следущем операнде, т.е. после ";". там оно будет на единицу больше,
а в самом выражении если ты в двух местах используешь
одну и ту же переменную и в одном месте ту ее используешь так: c++, то
не известно c будет увиличено сразу после или еще раз используется ее значение,
а только потом будет прибавление единицы
это в любой нормальной книжке по C написано.
так что если ты занимаешься програмированием, то лучше иди в дворники
>Никак нет. Все будет зависеть и от компилятора, и от оптимизатора: или постинкремент произойдет _до_ присвоения, или после. UB это. Курить стандарт языка.
Еще и от проца\архитектуры зависит. На 86 свет клином не сошелся (типа то что неоптимизированый компилер наваял не догмат). А курить стандарт бестолку. Надо на толстом картоне распечатать и в туалет вместо туалетной бумаги. Пока мять будет глядишь прочитает :)
************************************************************* Оператор ++NC; демонстрирует новую операцию, ++, которая означает увеличе- ние на единицу. Вы могли бы написать NC = NC + 1 , но ++NC более кратко и зачастую более эффективно. Имеется соответст- вующая операция -- уменьшение на единицу. Операции ++ и -- могут быть либо префиксными (++NC), либо постфиксными (NC++); эти две формы, как будет показано в главе 2, имеют в выражениях различные значения, !но как ++NC, так и NC++ уве- личивают NC!.
Необычный аспект заключается в том, что ++ и -- можно использовать либо как префиксные операции (перед переменной, как в ++N), либо как постфиксные (после переменной: N++). Эффект в обоих случаях состоит в увеличении N. Но выражение ++N увеличивает переменную N до использования ее значения, в то время как N++ увеличивает переменную N после того, как ее значение было использовано. Это означает, что в контексте, где используется значение переменной, а не только эффект увеличения, использование ++N и N++ приводит к разным ре- зультатам. Если N = 5, то х = N++; устанавливает х равным 5, а х = ++N; полагает х равным 6. В обоих случаях N становится равным 6.
> Какая разница в данной ситуации когда произойдет постинкремент. В любом случае будет 1.
Ты так и не понял. У нас _три_ действия:
1. Вычисление _значения_ выражения (i++), которое _всегда_ будет происходить первым (сначала вычисляется правая часть).
2. Присвоение переменной i _значения_, из (1.).
3. Инкремент переменной i (i+=1).
При этом (2.) и (3.) компилятор может расположить в любом порядке. В зависимости от ключей оптимизации, прилегающего кода и погоды на солнце.
То есть может быть как
t = i; // _значение_ (i++) _всегда_ равно i.
i = t;
i += 1;
так и
t = i;
i += 1;
i = t;
Возможный порядок действий и количество сочетаний для так любимого всеми
>Хорошо, а в чем практическая полезность такого поведения? Что мы приобретаем за счет этого?
Ничего. Но это _стандарт_. Это последняя инстанция, разрешающая подобные религиозные споры. И она говорит, что поведение _не определено_. А значит программа - некорректна.
И вообще, не забывай, что последний стандарт был принят в 99 году, немного позже написания книги (хотя когда были введены точки следования - точно не скажу). Такие вопросы решает _только_ стандарт, книги нужны лишь для разъяснения и обучения.
Извиняюсь за несколько сумбурный пост. 4.0 - по мнению многих разработчиков, выпустили преждевременно, х.з. из каких соображенний. Туда слили не до конца доработаный и оттестированный оптимизатор из ветки 4.1. А осталось вроде совсем немного 8). Поэтому если доработка не затянется, то свет увидит раньше 4.1 нежели 4.0.1.
> 1. Вычисление _значения_ выражения (i++), которое _всегда_ будет происходить первым (сначала вычисляется правая часть). 2. Присвоение переменной i _значения_, из (1.). 3. Инкремент переменной i (i+=1).
> При этом (2.) и (3.) компилятор может расположить в любом порядке. В зависимости от ключей оптимизации, прилегающего кода и погоды на солнце.
То, что он располагает их в произвольном порядке, - это его сексуальная проблема. То, что он при этом не получает ПРАВИЛЬНЫЙ ответ - это его ВИНА. Я, как программер на C, не обзязан вдаваться в подробности о том, насколько криво реализован сам компилер или оптимизация в нём. У меня есть книжка/стандарт, где чётко описано, что должно получиться. и ВСЁ. То, что компилер выдаёт что-то иное, не должно прикрываться фиговыми листочками типа "UB". ЭТО - БАГ, который никто не желает фиксить.
> Ничего. Но это _стандарт_. Это последняя инстанция, разрешающая подобные религиозные споры. И она говорит, что поведение _не определено_. А значит программа - некорректна.
Момент. Что, в изначальном стандарте языка C тоже фигурировало позорное "UB"? Или оно было добавлено много позже, чтобы тем самым злостно покрывать НЕВЕРНОЕ поведение некоторых компиляторов? Даааа уж, разработали язычок, мля.
>То, что он располагает их в произвольном порядке, - это его сексуальная проблема. То, что он при этом не получает ПРАВИЛЬНЫЙ ответ - это его ВИНА. Я, как программер на C, не обзязан вдаваться в подробности о том, насколько криво реализован сам компилер или оптимизация в нём. У меня есть книжка/стандарт, где чётко описано, что должно получиться. и ВСЁ. То, что компилер выдаёт что-то иное, не должно прикрываться фиговыми листочками типа "UB". ЭТО - БАГ, который никто не желает фиксить.
Лажу не пишите и все ок будет ;)
это из серии, давайте в стандарте опишем все самые идиотские варианты написания, какие токо может придумать извращенный мозг програмиста, которому нечем занятся!
>Необычный аспект заключается в том, что ++ и -- можно использовать либо как префиксные операции (перед переменной, как в ++N), либо как постфиксные (после переменной: N++). Эффект в обоих случаях состоит в увеличении N. Но выражение ++N увеличивает переменную N до использования ее значения, в то время как N++ увеличивает переменную N после того, как ее значение было использовано. Это означает, что в контексте, где используется значение переменной, а не только эффект увеличения, использование ++N и N++ приводит к разным ре- зультатам. Если N = 5, то х = N++; устанавливает х равным 5, а х = ++N; полагает х равным 6. В обоих случаях N становится равным 6.
тут сразу видно из описания UB, что делать если x=N? От момента присвоения зависит N=6 или N=5, и что должно происходит конкретно не описано. Пока в стандарте не будет написано что N этом варианте будет равно 6 или 5, все эти обсуждения просто переливание из пустого в порожнее.
> Лажу не пишите и все ок будет ;) это из серии, давайте в стандарте опишем все самые идиотские варианты написания, какие токо может придумать извращенный мозг програмиста, которому нечем занятся!
Хорошо продуманный язык тем и отличается, что лажу на нём написать сложно - поведение программы ОДНОЗНАЧНО и очевидно. А поведение "как бог на дущу положит" - это проблема языка, а не программиста. Это ПОЗОР для языка.
> тут сразу видно из описания UB, что делать если x=N? От момента присвоения зависит N=6 или N=5, и что должно происходит конкретно не описано. Пока в стандарте не будет написано что N этом варианте будет равно 6 или 5, все эти обсуждения просто переливание из пустого в порожнее.
Вот-вот, о том и речь. Язык плохо продуман, потому что изначально слабан на коленке, да и потом его развитием и исправлением занимались спустя рукава.
А оно и так однозначно и очевидно, если не использовать запрещенные конструкции. Или ты из той разновидности луддитов, которые ругают молоток за то, что им можно попасть по пальцам, а ружье за возможность выстрелить в ногу?
Если хочешь пользоваться инструментом, будь добр прочитать инструкцию. И _следовать_ ей. А по дурости можно и йцк сломать.
> Хорошо продуманный язык тем и отличается, что лажу на нём написать сложно
Вместо "сложно" ты хотел написать "невозможно"? Да, сейчас модно ругать С за наличие адресной арифметики, за неявное преобразование типов и т.д. Но С -- это всего-навсего "универсальный макро-ассемблер", один из самых низкоуровневых языков программирования высокого уровня. ;) И он уже не раз доказал эффективность в этом качестве.
Но если из С убрать адресную арифметику, ввести обязательную проверку границ и строгую типизацию, то получится Паскаль в своем первозданном виде.
> Это ПОЗОР для языка
Нет. Это позор для кодера. Клеймо профнепригодности для писателя "анекдотов на С" вида 'i=i++'.
> Язык плохо продуман
Язык хорошо продуман, просто некоторые не читают "инструкцию по эксплуатации".
Я еще в начале девяностых подсовывал студентам подобные задачки на дом, когда разбирали ЯВУ. Или общий уровень образованности сейчас упал, или просто каждый недоучка мнит себя специалистом, но тогда студенты в массе своей _сами_ доходили до понимания, что тут НП. Подходили со словами: "Вы, вероятно, ошиблись в задании: тут неоднозначность возникает". Нельзя в пределах одного оператора дважды присвоить значение переменной.
PS. Если отвлечься от НП, то "правильней" будет считать `i=i++` === `NOP`;
может смотреть допустим в эту сторону и постепенно гнутую кривость послать подальше. быстрый C КОМПИЛЯТОР есть - tcc. собираются им программы нормально и быстро но c++ там нет.