Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Почему такой результат???


Автор: it_medved 10.5.2007, 14:30
Не могу врубится, почему данное выражение приводит к результату 14...

Код

    int i = 5;
    i = ++i + ++i;

Автор: Fazil6 10.5.2007, 14:50
а какому результату оно должно приводить? Все правильно. 2 раза проинкрементировал. 7 + 7 = 14.

Автор: Anikmar 10.5.2007, 14:51
Думаю с точки зрения раскрутки и очередности операций все правильно:
1-е действие:
инкремент i. Результат помещается в i (6)
2-е действие:
инкремент i. Результат помещается в i (7)
3-е действие
Берется значение i (7) И прибавляется к значению i(7) - результат 14.

А вот с точки зрения здравого смысла - судить не берусь.

Автор: Daevaorn 10.5.2007, 15:00
Это UB. Результат может быть любым

Автор: Anikmar 10.5.2007, 15:03
Цитата(Daevaorn @  10.5.2007,  15:00 Найти цитируемый пост)
Это UB. Результат может быть любым 

А что такое UB?

Результат не может быть любым.
Он может быть либо 12 либо 13 либо 14

С точки зрения здравого смысло (имхо) ожидается 13

Автор: nerezus 10.5.2007, 15:11
Цитата

UB
 Неопределенное поведение. Зависит от реализации.

Автор: Daevaorn 10.5.2007, 15:11
Цитата(Anikmar @  10.5.2007,  16:03 Найти цитируемый пост)
А что такое UB?

http://en.wikipedia.org/wiki/Undefined_behavior
Цитата(Anikmar @  10.5.2007,  16:03 Найти цитируемый пост)
Результат не может быть любым.
Он может быть либо 12 либо 13 либо 14

С точки зрения здравого смысло (имхо) ожидается 13 

даже три варианта уже есть. но с там же успехом может быть и значение, например 666

Автор: Xenon 10.5.2007, 15:23
Это стопудовый  UB. Даже у Страуструпа четко прописано.

Автор: Anikmar 10.5.2007, 15:29
Цитата(Daevaorn @  10.5.2007,  15:11 Найти цитируемый пост)
даже три варианта уже есть. но с там же успехом может быть и заначени, например 666 

Разве может быть абсолютно любое?

Я считал, что только в рамках последовательности операций. И у Страуструпа по-моему именно так и описывается: последовательность зависит от реализации.

Но меньше 11 результат быть не может, так же как и больше 14.

Автор: zkv 10.5.2007, 15:38
Цитата(Anikmar @  10.5.2007,  15:29 Найти цитируемый пост)
Разве может быть абсолютно любое?

Я считал, что только в рамках последовательности операций. И у Страуструпа по-моему именно так и описывается: последовательность зависит от реализации.

Но меньше 11 результат быть не может, так же как и больше 14. 

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

Автор: Daevaorn 10.5.2007, 15:44
Цитата(Anikmar @  10.5.2007,  16:29 Найти цитируемый пост)
Разве может быть абсолютно любое?

если это UB, то может быть всё что угодно. Любые варианты - это гадание на кофейной гуще.

Автор: Anikmar 10.5.2007, 15:58
Цитата(zkv @  10.5.2007,  15:38 Найти цитируемый пост)
да какая разница, абсолютно любое или какое то из определенного множества, в любом случае использовать такой код нельзя. 


Цитата(Daevaorn @  10.5.2007,  15:44 Найти цитируемый пост)
если это UB, то может быть всё что угодно. Любые варианты - это гадание на кофейной гуще. 


Налетели!

Согласен я, естественно, просто из врожденной вредности: не любое, а из перечня (псевдо) неправильных результатов - вот я и занудствую.  smile 

Проехали. 

Вывод: Так делать нельзя. (Таракан без ног не слышит!)


Автор: nickless 10.5.2007, 16:04
http://www.research.att.com/~bs/bs_faq2.html#evaluation-order
Даже пример тот же smile 

Автор: it_medved 10.5.2007, 18:22
Фу, зардражают такие вопросики, неужели такая белиберда важна при реализации настоящей программы???

Автор: nickless 10.5.2007, 18:41
Цитата(it_medved @  10.5.2007,  17:22 Найти цитируемый пост)
неужели такая белиберда важна при реализации настоящей программы?

Ну почему белиберда? Не будешь знать об этом, обязательно где-нибудь что-то подобное напишешь (для "оптимизации" например, или чтоб код короче был), и будет такая программа потом работать только по полнолуниям smile 

Автор: it_medved 10.5.2007, 18:56
Да ну его, я таким бредом заниматся не буду smile 
И все же вернемся к вопросу. Я тут покумекал, и выходит, так
++i; // i==6
++i;// i==7
i+i// i==13... 
но с компилятором не поспоришь... это наверное как необьяснимое чудо

Автор: Hurricane 10.5.2007, 19:16
Цитата(it_medved @ 10.5.2007,  10:56)
Да ну его, я таким бредом заниматся не буду smile 
И все же вернемся к вопросу. Я тут покумекал, и выходит, так
++i; // i==6
++i;// i==7
i+i// i==13... 
но с компилятором не поспоришь... это наверное как необьяснимое чудо

Как это у тебя 7+7=13 получается - не понимаю  smile

Ну решил компилятор делать сложение после второго инкремента - такая у него логика.

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

Автор: it_medved 10.5.2007, 19:26
не гони! Читай внимательно!!! smile Там 6+7 smile

Добавлено через 1 минуту и 8 секунд
Так это все зависит от компилятора??? smile

Добавлено через 1 минуту и 50 секунд
UB - Universal Baran?

Автор: nickless 10.5.2007, 19:54
Цитата(it_medved @  10.5.2007,  18:26 Найти цитируемый пост)
Universal Baran

ага smile 
Undefined Behavior

Автор: dizzy1984 10.5.2007, 20:26
Цитата(it_medved @  10.5.2007,  18:56 Найти цитируемый пост)
Да ну его, я таким бредом заниматся не буду  
И все же вернемся к вопросу. Я тут покумекал, и выходит, так
++i; // i==6
++i;// i==7
i+i// i==13... 
но с компилятором не поспоришь... это наверное как необьяснимое чудо


Объяснение не сложное.
Выражение ++i + ++i. Нарушает правило которое гласит, что нельзя модифицировать переменную зажатую между 2-мя точками следования более 1-го раза. Это ведет к UB.
Здесь я так понимаю 1-я точка находится перед выражением, 2-я после.
Если сильно приперло, то можно переписать это выражение с использованием функции.

Код

int& inci(int &i) {return ++i};

i = inci(i) + inci(i);


Такой вариант всегда вернет ожидаемое.
Т.к каждая ф-я обрамлена точками следования.
Хотя порядок вычисления слагаемых все-равно не определен.

Автор: it_medved 10.5.2007, 20:28
Раз все пришли к такомы выводу, то будет правильным сказать тем, кто дает такие вопросы на тестах на приеме на работу (не будем говорить кто smile), что этот вопрос неправилен, потому как результат зависит от компилятора и UB(хотя что это такое я так и не понялsmile).

Автор: JackYF 10.5.2007, 20:44
Цитата(it_medved @  10.5.2007,  20:28 Найти цитируемый пост)
UB

Ну неопределенное поведение. То есть ни компилятор, ни стандарт не гарантируют тебе любого правила, по которому твое выражение будет вычислено.

В общем, такого надо избегать.

Автор: it_medved 10.5.2007, 20:51
А мне кажется, что состояние UB надо на уровне компиляции присваивать ошибку!

Автор: JackYF 10.5.2007, 20:56
Цитата(it_medved @  10.5.2007,  20:51 Найти цитируемый пост)
А мне кажется, что состояние UB надо на уровне компиляции присваивать ошибку!


а компилятор не факт, что сможет сам распознать UB. Хотя кто его знает...

Автор: turboNOMAD 10.5.2007, 20:57
А можно ткнуть меня носом в компилеры, которые тут выдают че-то другое, кроме 14? Самому лень искать

Автор: nickless 10.5.2007, 21:09
Цитата(it_medved @  10.5.2007,  19:51 Найти цитируемый пост)
А мне кажется, что состояние UB надо на уровне компиляции присваивать ошибку! 

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

Автор: it_medved 10.5.2007, 21:21
Цитата

Во всяком случае gcc выдаёт варнинг если компилировать с -Wall 
 
это как?

Автор: nickless 10.5.2007, 21:37
Цитата(it_medved @  10.5.2007,  20:21 Найти цитируемый пост)
это как? 

Код
$ g++ -Wall -o bla bla.cpp
bla.cpp: In function ‘int main()’:
bla.cpp:18: warning: operation on ‘i’ may be undefined
bla.cpp:18: warning: operation on ‘i’ may be undefined

Автор: dizzy1984 10.5.2007, 22:20
Цитата(it_medved @  10.5.2007,  20:28 Найти цитируемый пост)
хотя что это такое я так и не понял

Запускаешь свою программу, она начинает форматировать твой жесткий диск

Автор: Rockie 10.5.2007, 23:07
it_medved, "проверка на вшивость"? Эта тема уже поднималась, implementation-defined



Автор: nerezus 10.5.2007, 23:16
Цитата

А можно ткнуть меня носом в компилеры, которые тут выдают че-то другое, кроме 14? Самому лень искать
 perl выдал 13

Автор: turboNOMAD 11.5.2007, 15:09
Цитата(nerezus @ 10.5.2007,  23:16)
perl выдал 13

C# тоже, как известно, выдает 13. Я имел в виду сиплюсовые компиляторы ;)

Автор: JackYF 11.5.2007, 15:19
quote=nickless, 10.5.2007,  21:37, post1129056]$ g++ -Wall -o bla bla.cpp
bla.cpp: In function ‘int main()’:
bla.cpp:18: warning: operation on ‘i’ may be undefined
bla.cpp:18: warning: operation on ‘i’ may be undefined[/quote]

Просто замечательно! Я сам не пробовал, но варнинг - это уже хорошо.
По крайней мере, есть предупреждение.

Автор: smartov 11.5.2007, 18:06
nerezus, у меня перл выдал 14. Perl 5.8.8 Linux 

Проверил на других языках
PHP, Javascript, (и как сказали C#) - 13

Автор: Ignat 11.5.2007, 18:31
Господа, я не претендую на хорошее знание сей, но ткните меня носом в UB.
UB у нас будет в случае использования постфиксного инкремента, когда переменная для последующих операций берется по значению.
В случае же префиксного инкремента результат операции инкремента всегда будет возвращен по ссылке. Приоритет инкремента всегда выше сложения (не путайте с унарной операцией +). Следовательно результат данного выражения в C/C++ гарантирован.

Пожалуйста, поправьте, мне самому стало интересно smile

Автор: Любитель 11.5.2007, 19:00
Ignat, по-моему именно эту ссылочку уже приводили, но всё же:

http://www.research.att.com/~bs/bs_faq2.html#undefined - из хоум пйдж Бьярни Строуструпа.

Добавлено через 4 минуты и 55 секунд
Цитата(Bjarne Stroustrup)

int i = 10;
int j = ++i + i++;

<...>

the order of evaluation of arguments is unspecified

Автор: _stranger_ 11.5.2007, 19:24
и еще дополнение к вышесказанному:
ISO/IEC 14882 C++
5. Expressions. Clause 4
Цитата

Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression. ... otherwise the behavior is undefined

перевод на русский: между последовательными точками исполнения скалярный объект может меняться не более одного раза в результате вычисления выражения. ... Иначе результат не определен (UB).



Автор: Hurricane 11.5.2007, 19:26
Цитата(Ignat @ 11.5.2007,  10:31)
В случае же префиксного инкремента результат операции инкремента всегда будет возвращен по ссылке.

Это можно как-то гарантировать?  smile Имеется ввиду не только для int, но и возможную кривую реализацию перегруженного оператора класса. Да и для int, похоже, что одни компиляторы использую ссылку (результат 14), другие - копию (результат 13).

Автор: Promitheus 11.5.2007, 19:38
Код

int i=5;
i=++i + ++i + ++i;//выдает 24


Может быть они в С++ всё так и задумали.

Идём слева направо встречаем ++i, меняем содержимое на +1 , далее встречаем +, смотрим , что далее ++i у него больше приоритет, выполняем его, далее встречаем +, но за ним ++i - выполняем. А потом уже выполняем сложение, но в качестве аргументов не значение числовое, а значание которое находится по адресу в памяти у переменной i. Т.е. при выполнении операций он запоминает не числовое значение, а указатель на область памяти, а потом выполняет с этими указателями операции более низкого приоритета. 

Это то, как мне видется такое поведение компилятора. Впринципе, нечего необычного в поведении нету. Это чисто мои догадки, как на самом деле реализовано, я естественно не знаю.

На асме бы всё это надо написать.... мож понятнее будет. 

Автор: nickless 11.5.2007, 19:47
Я не понимаю, ну зачем зря гадать что получится, написано UB, значит UB.
Конечно в каждом компиляторе это как-то реализовано, и в польшинстве случаев он выдаст один и тот же результат, но это абсолютно не гарантирует, что результат не будет другим со включеной оптимизацией, после изменения кода в другом файле проекта, с новой версией компилятора или после внезапного лунного затмения. Нравится плясать с бубном?

Автор: zkv 11.5.2007, 19:49
Цитата(Promitheus @  11.5.2007,  19:38 Найти цитируемый пост)
int i=5;
i=++i + ++i + ++i;//выдает 24

я пошел еще дальше, и установил следующие факты:
Код

int i=5;
i=++i + ++i + ++i + ++i;//выдает 36

Код

int i=5;
i=++i + ++i + ++i + ++i + ++i;//выдает 48

Мне кажется, что компилятор интерпретирует выражение "+ ++i"  как "прибавить 12"
Завтра попробую продолжить эксперименты.

PS Шутка smile
PPS Наврал, в последнем не 48 получается, придется искать другое объяснение...

Автор: Любитель 11.5.2007, 19:52
Цитата(Promitheus @  11.5.2007,  19:38 Найти цитируемый пост)
//выдает 24

Да ну. Ты уверен?

На вскидку - после компайла MinGW и запуска, получаем 22 smile

Андефинед бехаувер и всё! Хватит собственные варианты придумывать! Есть стандарт, который чётко определяет, что мы должны и когда получить. И он определяет, что в данной ситуации мы можем получить, что угодно.

Всё!

Автор: Hurricane 11.5.2007, 19:58
Цитата(Любитель @ 11.5.2007,  11:52)
Андефинед бехаувер

 smile 

Ай лайк йор джёрмен аксент!  smile 

Автор: Promitheus 11.5.2007, 20:13
Любитель

Код

int i=5;
i=++i + ++i + ++i;
ShowMessage(i);

В 6 Билдере прям в конструктор формы затолкай и откомпили, посмотришь, что получится - 24. 
__

Ну вообще да это какое-то шаманство ...  i=++i + ++i + ++i + ++i + ++i; полтос выдаёт  smile 

Автор: Любитель 11.5.2007, 20:22
Млин, уже обсудили. В билдере - 24, в MinGW - 22. Где-нибудь 23. Теоритечески может получится, скажем 115. Это будет формально удовлетворять стандарту, ибо по стандарту неизвестно, что должно получиться.

 smile 
Цитата(Hurricane @  11.5.2007,  19:58 Найти цитируемый пост)
Ай лайк йор джёрмен аксент!

А как правильно произносить? А то интересно стало smile

А так - ракладки лень переключать smile

Автор: EvgenZ 11.5.2007, 20:23
//это уже на BrainFuck смахивает )))))
Я знал, что без скобочек такое писать нельзя, но думал, что можно так
(++i) + (++i);

 smile 

Автор: Hurricane 11.5.2007, 20:59
Цитата(Любитель @ 11.5.2007,  12:22)
Цитата(Hurricane @  11.5.2007,  19:58 Найти цитируемый пост)
Ай лайк йор джёрмен аксент!

А как правильно произносить? А то интересно стало smile

А так - ракладки лень переключать smile

 smile 

Ну, по последним указаниям ЦК ВЦСПС что-то вроде Андифайнд Бихейвьёр.  smile Хотя жители Соединенного Королевства могут и с этим не согласиться.

Автор: JackYF 11.5.2007, 20:59
Цитата(Любитель @  11.5.2007,  20:22 Найти цитируемый пост)
А как правильно произносить? А то интересно стало


Насколько мне позволяет мой английский - "андефайнед бихавиэр"

Автор: nickless 11.5.2007, 22:03
Цитата(Любитель @  11.5.2007,  19:22 Найти цитируемый пост)
А как правильно произносить?

 smile Раз уж на то пошло smile :
http://www.answers.com/undefined
http://www.answers.com/topic/behavior


Автор: BreakPointMAN 11.5.2007, 23:09
Наверное, у всех временное помешательство, то ли звезды так расположены, то ли... На нескольких форумах в одно и то же время обсуждают одну и ту же тему... Бррр... Вы  проhttp://alenacpp.blogspot.com/2005/11/sequence-points.html что-нибудь слышали?

Автор: Daevaorn 11.5.2007, 23:17
Цитата(BreakPointMAN @  12.5.2007,  00:09 Найти цитируемый пост)
Вы  проточки следования что-нибудь слышали?

тут про них уже говорили

Автор: Любитель 11.5.2007, 23:45
[offtop]
Цитата(nickless @  11.5.2007,  22:03 Найти цитируемый пост)
Раз уж на то пошло
...

На behavior у меня почему-то звук не открывается smile (туоп запрос идёт - ответа нет)...

Мои преогромнейшие извинения за тягчайшее нарушение правил инглиш спикинг smile 
[/offtop]

Автор: Hurricane 12.5.2007, 00:44
 smile 

Цитата(nickless @ 11.5.2007,  14:03)
Раз уж на то пошло smile :
http://www.answers.com/undefined
http://www.answers.com/topic/behavior



Молодец!  smile А теперь всю фразу вместе повторить сможешь?  smile 

Цитата(Любитель @ 11.5.2007, 15:45)
Мои преогромнейшие извинения за тягчайшее нарушение правил инглиш спикинг 


Любитель, ну это же шутка была...  smile 

Все, обещаю больше не хулиганить с оффтопами.


Автор: JackYF 12.5.2007, 00:59
Цитата(BreakPointMAN @  11.5.2007,  23:09 Найти цитируемый пост)
Бррр... Вы  проточки следования что-нибудь слышали? 


Занимательно. Но это теория. А то, что обсуждаемое выражение приводит к UB, и так уже выяснили.

Автор: Любитель 12.5.2007, 01:08
Цитата(Hurricane @  12.5.2007,  00:44 Найти цитируемый пост)
Любитель, ну это же шутка была...

эээ... а я типа серьёзно говорю что ли smile Так - делать нечего...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)