powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Префиксные операции и стандарт
25 сообщений из 55, страница 1 из 3
Префиксные операции и стандарт
    #33716795
Карабас Барабас
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всем добрый день.

вот такой код:
Код: plaintext
1.
2.
  int a= 1 ;
  a=(++a)+(++a);
на первый взгляд выдает неправильный результат 6 :), хотя если посмотреть ассемблерный код и подумать, то вроде как все правильно: префиксный оператор ++ выполняется ДО ИСПОЛЬЗОВАНИЯ переменной, это можно понимать и как ДО ВЫЧИСЛЕНИЯ ВСЕГО ВЫРАЖЕНИЯ, а раз переменная используется в выражении и есть префиксная операция с ней (++), то переменная должна быть увеличена. Раз таких операций 2, то переменная увеличивается дважды, никакой самодеятельности, просто незнание или недопонимание работы компилятора.
Кстати, если уж необходимо гарантированное однократное увеличение, то можно и так написать:
Код: plaintext
1.
2.
3.
4.
  int a= 1 ;
  int &b=a;
  int &c=a;
  a=(++b)+(++c);
выдает 5, хотя ссылочные переменные считаются просто вторым именем (где-то однажды вычитал такую трактовку) :)

Вобщем то понятно, подобные примеры - это road to hell.

Мнения ?
Posted via ActualForum NNTP Server 1.3
...
Рейтинг: 0 / 0
Префиксные операции и стандарт
    #33716842
x_0040h
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Так а вопрос то в чём? Всё правильно, всё работает. Если у кого то труднос пониманием таких конструкций пусть их не использует.
...
Рейтинг: 0 / 0
Префиксные операции и стандарт
    #33716861
Карабас Барабас
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
x_0040h
x> Так а вопрос то в чём? Всё правильно, всё работает. Если у
x> кого то труднос пониманием таких конструкций пусть их не
x> используетИнтересуют мнения - соответствует такое поведения компилятора стандарту или нет.
Posted via ActualForum NNTP Server 1.3
...
Рейтинг: 0 / 0
Префиксные операции и стандарт
    #33716893
ZrenBy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Карабас Барабасвот такой код:
Код: plaintext
1.
2.
  int a= 1 ;
  a=(++a)+(++a);


5/4 "... behavior is undefined"
...
Рейтинг: 0 / 0
Префиксные операции и стандарт
    #33716917
Фотография v6y
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Карабас Барабас x_0040h
x> Так а вопрос то в чём? Всё правильно, всё работает. Если у
x> кого то труднос пониманием таких конструкций пусть их не
x> используетИнтересуют мнения - соответствует такое поведения компилятора стандарту или нет.
Posted via ActualForum NNTP Server 1.3
Какой компилятор используешь? У меня все имеющиеся в распоряжении gcc в обоих случаях 6 выдали.
...
Рейтинг: 0 / 0
Префиксные операции и стандарт
    #33716919
x_0040h
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ZrenBy
5/4 "... behavior is undefined"
Опредил =)

Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual
expressions, and the order in which side effects take place, is unspecified. 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. Furthermore, the prior value shall be accessed only to determine the value to be stored. The
requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full
expression; otherwise the behavior is undefined. [Example:
i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // ‘i’ becomes 9
i = ++i + 1; // the behavior is undefined
i = i + 1; // the value of ’i’ is incremented
—end example]
...
Рейтинг: 0 / 0
Префиксные операции и стандарт
    #33716939
Карабас Барабас
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
v6yКакой компилятор используешь?C++Builder 5.0
Posted via ActualForum NNTP Server 1.3
...
Рейтинг: 0 / 0
Префиксные операции и стандарт
    #33716982
Фотография v6y
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
x_0040h ZrenBy
5/4 "... behavior is undefined"
Опредил =)

Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual
expressions, and the order in which side effects take place, is unspecified. 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. Furthermore, the prior value shall be accessed only to determine the value to be stored. The
requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full
expression; otherwise the behavior is undefined. [Example:
i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // ‘i’ becomes 9
i = ++i + 1; // the behavior is undefined
i = i + 1; // the value of ’i’ is incremented
—end example]
То что в зависимости от компилятора будет разный результат и ежу понятно. Но поскольку такие конструкции не запрещены, то вопрос о неком стандарте по вычислению подобных выражений имеет право быть, ИМХО.

2Карабас Барабас
Скорее всего зависит от способа получения/вычисления дерева выражений того или иного компилятора. Лично мне понятен случай когда в обоих примерах получаем 6. А вот почему второй пример у тебя возвращает 5... Может x_0040h объяснит? ;-).
...
Рейтинг: 0 / 0
Префиксные операции и стандарт
    #33716990
Карабас Барабас
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
v6yА вот почему второй пример у тебя возвращает 5Меня это тоже озадачило :)
Ассемблерный код совершенно другой генерится.

кстати, вот такой код:
Код: plaintext
1.
2.
3.
  int a= 1 ;

  a=(a=a+ 1 )+(a=a+ 1 );
выдает тоже 5
Posted via ActualForum NNTP Server 1.3
...
Рейтинг: 0 / 0
Префиксные операции и стандарт
    #33717050
x_0040h
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Предлагаю Вам господа выложить сюда ассемблерный код, который генерирует ваш компилятор, потому как мой при любых вариантах кода представленных здесь выдаёт 6 (MSVS 2005(восьмёрка)).
...
Рейтинг: 0 / 0
Префиксные операции и стандарт
    #33717070
Карабас Барабас
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
x_0040h
x> Предлагаю Вам господа выложить сюда ассемблерный код,
x> который генерирует ваш компилятор, потому как мой при
x> любых вариантах кода представленных здесь выдаёт 6 (MSVS
x> 2005(восьмёрка))
C++Builder 5.0:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
    int a= 1 ;
    a=(++a)+(++a);


 mov       dword ptr [ebp- 12 ], 1 
 inc       dword ptr [ebp- 12 ]
 inc       dword ptr [ebp- 12 ]
 mov       eax,dword ptr [ebp- 12 ]
 add       dword ptr [ebp- 12 ],eax
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
    int a= 1 ;
    int &b=a;
    int &c=a;
    a=(++b)+(++c);


 mov       dword ptr [ebp- 16 ], 1 
 lea       edx,dword ptr [ebp- 16 ]
 mov       dword ptr [ebp- 20 ],edx
 lea       ecx,dword ptr [ebp- 16 ]
 mov       dword ptr [ebp- 24 ],ecx
 mov       eax,dword ptr [ebp- 20 ]
 inc       dword ptr [eax]
 mov       edx,dword ptr [eax]
 mov       ecx,dword ptr [ebp- 24 ]
 inc       dword ptr [ecx]
 mov       eax,dword ptr [ecx]
 add       edx,eax
 mov       dword ptr [ebp- 16 ],edx
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
    int a= 1 ;

    a=(a=a+ 1 )+(a=a+ 1 );


 mov       dword ptr [ebp- 28 ], 1 
 inc       dword ptr [ebp- 28 ]
 mov       edx,dword ptr [ebp- 28 ]
 inc       dword ptr [ebp- 28 ]
 mov       ecx,dword ptr [ebp- 28 ]
 add       edx,ecx
 mov       dword ptr [ebp- 28 ],edx

Posted via ActualForum NNTP Server 1.3
...
Рейтинг: 0 / 0
Префиксные операции и стандарт
    #33717112
Карабас Барабас
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Карабас БарабасC++Builder 5.0То же, но после включения оптимизации:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
    int a= 1 ;
    a=(++a)+(++a);

 mov       eax, 1 
 inc       eax
 inc       eax
 add       eax,eax
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
    int a= 1 ;
    int &b=a;
    int &c=a;
    a=(++b)+(++c);

 mov       dword ptr [esp], 1 
 mov       eax,esp
 mov       edx,esp
 inc       dword ptr [eax]
 mov       ecx,dword ptr [eax]
 inc       dword ptr [edx]
 mov       eax,dword ptr [edx]
 add       ecx,eax
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
    int a= 1 ;

    a=(a=a+ 1 )+(a=a+ 1 );

 mov       eax, 1 
 inc       eax
 mov       edx,eax
 inc       eax
 add       edx,eax

Posted via ActualForum NNTP Server 1.3
...
Рейтинг: 0 / 0
Префиксные операции и стандарт
    #33717533
maXmo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gcc manProblems often result from expressions with two increment operators, as in f (*p++, *p++). Your previous compiler might have interpreted that expression the way you intended; GCC might interpret it another way. Neither compiler is wrong. The bug is in your code.
Код: plaintext
1.
2.
3.
4.
 mov       edx,dword ptr [eax]
 mov       ecx,dword ptr [ebp-24]
 inc       dword ptr [ecx]
 mov       eax,dword ptr [ecx]
 add       edx,eax
алиасинг - это офигенная головная боль для компилятора.
------------------
- А как в Интеpнете pаботать? - Сначала нужно узнать, что вам нужно rtfm
...
Рейтинг: 0 / 0
Префиксные операции и стандарт
    #33717698
maXmo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
manThe C and C++ standards have the notion of "sequence points". Everything that happens between two sequence points happens in an unspecified order, but it has to happen after the first and before the second sequence point. The end of a statement and a function call are examples for sequence points, whereas assignments and the comma between function arguments are not. http://gcc.gnu.org/bugs.html#nonbugs_c
...
Рейтинг: 0 / 0
Префиксные операции и стандарт
    #33717724
maXmo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
http://publications.gbdirect.co.uk/c_book/chapter8/sequence_points.html
------------------
- А как в Интеpнете pаботать? - Сначала нужно узнать, что вам нужно rtfm
...
Рейтинг: 0 / 0
Префиксные операции и стандарт
    #33717748
maXmo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a=(++a)+(++a);
так что стандарт говорит, что может быть всё что угодно, но на моё имхо должно быть 5 :)
------------------
- А как в Интеpнете pаботать? - Сначала нужно узнать, что вам нужно rtfm
...
Рейтинг: 0 / 0
Префиксные операции и стандарт
    #33717799
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Результат по стандарту не определен. Компилироваться такой код обязан без ошибок. Как он будет работать стандарт не оговаривает. Это все насколько я знаю. Т.е. такое поведение компилятора полностью соответствует стандарту.
...
Рейтинг: 0 / 0
Префиксные операции и стандарт
    #33717818
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Это, а объясните, как там 6-то может получиться ?
...
Рейтинг: 0 / 0
Префиксные операции и стандарт
    #33717839
Карабас Барабас
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivкак там 6-то может получиться ?лихко: 3+3=6
Posted via ActualForum NNTP Server 1.3
...
Рейтинг: 0 / 0
Префиксные операции и стандарт
    #33717984
x_0040h
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZivЭто, а объясните, как там 6-то может получиться ?
ИМХО 6 там просто обязано получится.
Возьмём например

a=(++a)+(++a); //скобки кстати можно убрать, инкремент приоритетней.

Сначала срабатывает левый инкремент "а", и "а" становится равным 2.
Потом срабатывет правый инкремент и "а" становится равным 3.
Потом "а" складывается с "а" 3+3=6.
Мне кажется всё логично с точи зрения компилятора, если рассматривать "а" как ячейку памяти значение в которой дважы инкрементируется и складывается само с собой. В конечном итоге мы же складываем значения в памяти, а не какие то абстрактные понятия.
ИМХО логика borland-овского компилятора, который сохраняет результат выполения левого инкремента во временное хранилище не верна.
...
Рейтинг: 0 / 0
Префиксные операции и стандарт
    #33717995
Карабас Барабас
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
x_0040hИМХО логика borland-овского компилятора, который сохраняет результат выполения левого инкремента во временное хранилище не вернаНичгео он не сохраняет, у меня в этом примере получилось 6.
5 получилось в других примерах: со ссылками и с присваиванием
Posted via ActualForum NNTP Server 1.3
...
Рейтинг: 0 / 0
Префиксные операции и стандарт
    #33718035
Фотография v6y
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если я правильно понял Карабаса Барабаса, то его интересует как, по мнению форумчан, должны вычисляться подобные выражения. И если я понял его правильно, то тогда я не понял чего народ тут усиленно толкует о том что дважды два четыре (результат по стандарту не определен бла-бла-бла)

Я тут по-медитировал, и тоже пришел к мнению, что
Код: plaintext
1.
2.
 int a= 1 ;
 a=(++a)+(++a);
наверное правильнее а=5, т.е. перед вычислением хранить промежуточные значения операндов.
В что-то типа польской записи: (PREINCa)(PREINCa)+
PREINCa=2
PREINCa=3
2+3=5
И код генерировать соответсвующий.
...
Рейтинг: 0 / 0
Префиксные операции и стандарт
    #33718043
maXmo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
x_0040hИМХО 6 там просто обязано получится.м-да? А если а - объект пользовательского класса с переодределёнными операторами + и ++ ?

а скомпиль такую штуку:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
inline int inc(int &i)
{ return ++i; }

main()
{
 int a= 1 ;
 a=inc(a)+inc(a);
}
...
Рейтинг: 0 / 0
Префиксные операции и стандарт
    #33718052
x_0040h
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Карабас Барабас x_0040hИМХО логика borland-овского компилятора, который сохраняет результат выполения левого инкремента во временное хранилище не вернаНичгео он не сохраняет, у меня в этом примере получилось 6.
5 получилось в других примерах: со ссылками и с присваиванием
Posted via ActualForum NNTP Server 1.3
Видимо я вас неправильно понял. Но и код со ссылками в MSVS выдаёт 6. Лично я считаю такой резуьтат верным и ожидаемым.
...
Рейтинг: 0 / 0
Префиксные операции и стандарт
    #33718289
x_0040h
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
maXmo x_0040hИМХО 6 там просто обязано получится.м-да? А если а - объект пользовательского класса с переодределёнными операторами + и ++ ?

а скомпиль такую штуку:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
inline int inc(int &i)
{ return ++i; }

main()
{
 int a= 1 ;
 a=inc(a)+inc(a);
}


А скомпиль такую штуку:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
inline int& inc(int &i)
{ return ++i; }

main()
{
 int a= 1 ;
 a=inc(a)+inc(a);
}
ИМХО логичнее при операции инкремента возвращать самого себя(имеется в виду ссылку на самого себя), потому что ты модифицируешь собственное состояние, а не экземпляр только что созданного и модифицированной операцией инкремента класса в новой ячейке памяти. При твоём варианте(ничего что на ты? года позволяют? ;) ) вполне естественно на месте компилятора создать темповую переменную которую он потом благополучно сложит.

Наверное это всё таки пустой спор из разряда Linux vs Wndows, хотя всё таки можешь попробовать меня переубедить(если не жалко рабочего времени - читай денег работодателя), что надо возвращать экземпляр а не ссылку при перегрузке оператора инкремента.

PS: кстати на собеседованиях иногда спрашивают такого рода вопросы, но форма обычно "что быдет, если вызвать f(++p,++p); и что будет если f(++p,p++);"
...
Рейтинг: 0 / 0
25 сообщений из 55, страница 1 из 3
Форумы / C++ [игнор отключен] [закрыт для гостей] / Префиксные операции и стандарт
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]