Рассмотрим следующее утверждение. Каким будет значение, сохраненное в b?
int a=1;
int b = a+=1 ? a+=1 : 10;
Я получаю ответ как 4. Может ли кто-нибудь объяснить, как это работает.
Рассмотрим следующее утверждение. Каким будет значение, сохраненное в b?
int a=1;
int b = a+=1 ? a+=1 : 10;
Я получаю ответ как 4. Может ли кто-нибудь объяснить, как это работает.
Это связано с приоритетом. Если вы посмотрите на следующий код (с самым правым a+=1
измененным для простоты):
#include <iostream>
int main (void) {
int a=1;
int b = a+=1 ? 7 : 10;
std::cout << b << std::endl;
return 0;
}
вы увидите, что вывод 8
, а не 7
или 10
.
Это потому, что утверждение:
int b = a+=1 ? 7 : 10;
интерпретируется как:
int b = (a += (1 ? 7 : 10));
Теперь, применив это к вашему делу, получим:
int b = (a += (1 ? a += 1 : 10));
и, в порядке выполнения:
a += 1
(так как 1
- true) устанавливает a
в 2
.a += 2
(2
является результатом предыдущего шага) устанавливает a
в 4
.b = 4
(4
является результатом предыдущего шага).Просто имейте в виду, что вы не можете обязательно полагаться на этот порядок оценки. Несмотря на то, что в ?
есть точка последовательности (так что 1
оценивается полностью до продолжения), нет никакой точки последовательности между самой правой a += ...
и самой левой a += ...
. И изменение одной переменной дважды без промежуточной точки последовательности - это поведение undefined, поэтому gcc -Wall
предоставит вам очень полезное сообщение:
warning: operation on ‘a’ may be undefined
Тот факт, что он дает вам 4
, - это чистое совпадение. Это может так же легко дать вам 3
, 65535
или даже отформатировать жесткий диск, чтобы научить вас уроку: -)
Как указано в других ответах, эти два фрагмента кода эквивалентны из-за правил грамматики С++, которые определяют, как должны обрабатываться составные выражения.
int a=1;
int b = a+=1 ? a+=1 : 10;
и
int a=1;
int b = (a += (1 ? (a += 1) : 10));
Хотя в условном выражении есть точка последовательности, она находится между оценкой первого выражения (1
) и оценкой того, что оценивается одно из второго и третьего выражений (a += 1
в этом случае), После оценки второго или третьего выражения отсутствует явная дополнительная точка последовательности.
Это означает, что a
дважды изменяется в инициализаторе для b
без промежуточной точки последовательности, поэтому код имеет поведение undefined.
Анализ сборки:
int main()
{
int a=1;
int b = a+=1 ? a+=1 : 10;
return 0;
}
Сводный код, сгенерированный (используя MinGW) для приведенного выше кода, показан ниже. Комментарии мои, конечно! Читайте также комментарии!
call ___main //entering into main()
movl $1, 12(%esp) //int a = 1; means 12(%esp) represents a;
incl 12(%esp) //a+=1 ; a becomes 2
movl 12(%esp), %eax //loading 'a' onto a register(eax); eax becomes 2
addl %eax, %eax //adding the register to itself; eax becomes 4
movl %eax, 12(%esp) //updating 'a' with the value of eax; 'a' becomes 4
movl 12(%esp), %eax //this step could be optimized away; anyway it loads value of 'a' onto the register(eax); eax becomes 4, in fact even earlier it was 4 too! needless step!
movl %eax, 8(%esp) //loading the value of eax at another memory location which is 8(%esp); this location represents b;
movl $0, %eax //making eax zero! the return value of main()!
leave //now main() says, please leave me!
12(%esp)
представляют собой расположение памяти a
и на расстоянии 4 байта от него, то есть 8(%esp)
представляет b
. В конце значение в обоих этих ячейках памяти равно 4.
Следовательно, b = 4. Также a = 4.