Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум «Всё о Паскале» _ Ада и другие языки _ ++i

Автор: мисс_граффити 21.07.2007 22:08

здравствуйте...
есть небольшой кусочек кода:

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

java считает, что получается 13 (я с ней согласна...
0) ++i равно 6
1) ++i равно 7
2) 6+7=13)
а вот с++ (пользуюсь с++ builder 5) уверен, что 14.

вопрос: это фишка языка или компилятора (то есть что получится при использовании другого с++-ного компилятора)? и откуда, все же, берется 14?

Автор: volvo 21.07.2007 22:33

В С++ такое выражение по Стандарту вызывает UB (Undefined Behavior), и результат зависит от компилятора (но с точки зрения того же Стандарта программа содержащая такое выражение - некорректна).

Автор: мисс_граффити 21.07.2007 22:57

а в чем именно заключается некорректность?
в том, что можно рассматривать выражение не как
(++i) + (++i)
а как
((++i)++) + i
?
тогда действительно будет 14...

Автор: volvo 21.07.2007 23:01

Некорректность заключается в изменении одной переменной в пределах одного выражения (если точнее - между Sequence Points) более одного раза. Скобки положения не спасают, они Sequence Point не являются.

Автор: мисс_граффити 23.07.2007 3:06

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

Автор: hardcase 6.08.2007 22:30

Цитата(мисс_граффити @ 23.07.2007 0:06) *
нашла статейку по этому поводу, разобралась окончательно.
спасибо большое!

Темка устарела, но в догонку оставлю пост.
Вот результат дизассемблирования строки i = ++i + ++i (BDS2006, без какой либо оптимизации)
Код

Unit1.c.12: i = ++i + ++i;
0040117B FF45FC           inc dword ptr [ebp-$04]
0040117E FF45FC           inc dword ptr [ebp-$04]
00401181 8B45FC           mov eax,[ebp-$04]
00401184 0145FC           add [ebp-$04],eax

Видно,что сперва компилер выполнил ++i 2 раза, потом сложил и результат поместил снова в i.
В результате получаем 14.

Для Vs2005 можно увидеть такой код (без оптимизации)
Код

    i = ++i + ++i;
00401BFD  mov         eax,dword ptr [i]
00401C00  add         eax,1
00401C03  mov         dword ptr [i],eax
00401C06  mov         ecx,dword ptr [i]
00401C09  add         ecx,1
00401C0C  mov         dword ptr [i],ecx
00401C0F  mov         edx,dword ptr [i]
00401C12  add         edx,dword ptr [i]
00401C15  mov         dword ptr [i],edx

с оптимизацией всю кухную компилер заменил на инструкцию lea, i находится в eax
Код

i = ++i + ++i;
00401019  lea         eax,[eax+eax+4]

в обоих случаях получаем 14

Для C# в той же Vs2005 получим 13, вот листинг дизассемблирования:
Код

            int i = 5;
00000027  mov         esi,5
            i = ++i + ++i;
0000002c  inc         esi  
0000002d  mov         edi,esi
0000002f  inc         esi  
00000030  add         esi,edi

Автор: klem4 11.08.2007 23:58

Юль, а ссылочкой на статью не поделишься ? 10.gif

Автор: Neznaika 12.08.2007 0:13

i = ++i + ++i;
Оператор ++ используется только с ПЕРЕМЕННОЙ и производит ДВА результата:
1) сначала на 1 увеличивается i;
2) результат (++i) равен первоначальному значению i плюс 1.
Следовательно исходный оператор можно разделить на 3:
temp1 = ++i;
temp2 = ++i;
i = temp1 + temp2;
В каком порядке вычисляются temp1 и temp2 не имеет значения, поэтому, если сначала i = 5,
то после (i = ++i + ++i) i должно быть равно 13.
Правая часть вычисляется независимо от левой. I увеличивается на 1 всего два раза и далее в последней
операции сложения не участвует. Откуда BDS2006 и VS2005 получают 14???
Справа два (++i) зависят друг от друга, но левое i... Это же всего лишь приёмник. Разве не так?

Цитата

inc dword ptr [ebp-$04]
inc dword ptr [ebp-$04]
mov eax,[ebp-$04] ; eax = temp2 temp1 потерян.
add [ebp-$04],eax ; i = temp2 + temp2


Цитата

eax,dword ptr [i]
add eax,1
mov dword ptr [i],eax ; i = temp1
mov ecx,dword ptr [i]
add ecx,1
mov dword ptr [i],ecx ; i = temp2
mov edx,dword ptr [i]
add edx,dword ptr [i]
mov dword ptr [i],edx ; i = temp2 + temp2 ???


Теперь понятно, почему эти уроды у меня не живут.

Автор: volvo 12.08.2007 1:04

Цитата
Откуда BDS2006 и VS2005 получают 14???
Повторяю для особо внимательных: после Undefined Behavior результат программы будет непредсказуемым. И не надо ничего говорить про средства разработки, ты в зеркале ищи ошибку.

Когда тебе говорят "это нельзя делать, потому что...", а ты на это не обращаешь внимания, и делаешь, потому что ХОЧЕТСЯ, кто ж тебе виноват? Видно, никогда не отлаживал код, который после перехода на новую версию компилятора напрочь отказывался работать как требуется, и как работал на старой версии, а в проекте несколько тысяч файлов, и в одном из них какой-то м...к нарушил Стандарт. И пока ошибка не была найдена - аврал...

Автор: мисс_граффити 12.08.2007 13:59

Цитата(klem4 @ 11.08.2007 20:58) *

Юль, а ссылочкой на статью не поделишься ? 10.gif

поделюсь smile.gif
http://alenacpp.blogspot.com/2005/11/sequence-points.html

Цитата
и в одном из них какой-то м...к нарушил Стандарт

цитируя башорг:
Цитата
<******> к вопросу о вчерашних скриптостраданиях. Только что кодер знакомый прислал, нашёл в коде программы, написанной уволенным коллегой незадолго до ухода:
<******> #define TRUE FALSE //счастливой отладки с**и
****** такого извращённого юмора ещё не встречал