Consider the following statement. What will be the value stored in b?
int a=1;
int b = a+=1 ? a+=1 : 10;
I get the answer as 4. Can anyone explain how that works please.
It has to do with precedence. If you examine the following code (with the rightmost a+=1
changed for simplicity):
#include <iostream>
int main (void) {
int a=1;
int b = a+=1 ? 7 : 10;
std::cout << b << std::endl;
return 0;
}
you will see that the output is 8
, not 7
or 10
.
That's because the statement:
int b = a+=1 ? 7 : 10;
is being interpreted as:
int b = (a += (1 ? 7 : 10));
Now, applying that to your case, we get:
int b = (a += (1 ? a += 1 : 10));
and, in order of execution:
a += 1
(since 1
is true) sets a
to 2
. a += 2
( 2
is the result of the previous step) sets a
to 4
. b = 4
( 4
is the result of the previous step). Just keep in mind that you can't necessarily rely on that order of evaluation. Even though there is a sequence point at the ?
(so that 1
is evaluated fully before continuing), there is no sequence point between the rightmost a += ...
and the leftmost a += ...
. And modifying a single variable twice without an intervening sequence point is undefined behaviour, which is why gcc -Wall
will give you the very useful message:
warning: operation on ‘a’ may be undefined
That fact that it gives you 4
is pure coincidence. It could just as easily give you 3
, 65535
or even format your hard disk to teach you a lesson :-)
As stated in the other answers these two code snippets are equivalent due to the grammar rules of C++ which determine how compound expressions must be parsed.
int a=1;
int b = a+=1 ? a+=1 : 10;
and
int a=1;
int b = (a += (1 ? (a += 1) : 10));
Although there is a sequence point in a conditional-expression it is between the evaluation of the first expression ( 1
) and the evaluation of whichever one of the second and third expressions is evaluated ( a += 1
in this case). There is no explicit extra sequence point after the evaluation of the second or third expression.
This means that a
is modified twice in the initializer for b
without an intervening sequence point so the code has undefined behavior .
Assembly analysis:
int main()
{
int a=1;
int b = a+=1 ? a+=1 : 10;
return 0;
}
Assembly code generated (using MinGW) for the above code is shown below. The comments are mine, of course! Read the comments also!
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)
represent memory location of a
, and at a distance 4 byte from it, that is, 8(%esp)
represents b
. At the end, the value at both these memory locations is 4.
Hence, b = 4. Also a = 4.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.