Wednesday, 5 October 2016

c++ - When does postincrement i++ get executed?






Possible Duplicate:
Undefined Behavior and Sequence Points






In C++ on a machine code level, when does the postincrement++ operator get executed?



The precedence table indicates that postfix++ operators are level 2: which means in




int x = 0 ;
int y = x++ + x++ ; // ans: y=0


The postfix ++'s execute first.



However, it would seem that the logical operation of this line is the addition happens first (0+0), but how does that happen?



What I imagine, is the following:




// Option 1:
// Perform x++ 2 times.
// Each time you do x++, you change the value of x..
// but you "return" the old value of x there?
int y = 0 + x++ ; // x becomes 1, 0 is "returned" from x++

// do it for the second one..
int y = 0 + 0 ; // x becomes 2, 0 is "returned" from x++... but how?
// if this is really what happens, the x was already 1 right now.



So, the other option is although x++ is higher on the precedence table that x + x, the code generated due to x++ is inserted below the addition operation



// Option 2:  turn this into
int y = x + x ; //
x++ ;
x++ ;


That second option seems to make more sense, but I'm interested in the order of operations here. Specifically, when does x change?



Answer



Instead of jumping on the details of the example that is UB, I will discuss the following example that is perfectly fine:



int a = 0, b = 0;
int c = a++ + b++;


Now, the precedence of operators means that the last line is equivalent to:



int c = (a++) + (b++);



And not:



int c = (a++ + b)++; // compile time error, post increment an rvalue


On the other hand, the semantics of the post increment are equivalent to two separate instructions (from here on is just a mental picture):



a++; // similar to: (__tmp = a, ++a, __tmp) 

// -- ignoring the added sequence points of , here


That is, the original expression will be interpreted by the compiler as:



auto __tmp1 = a;         // 1
auto __tmp2 = b; // 2
++a; // 3
++b; // 4
int c = __tmp1 + __tmp2; // 5



But the compiler is allowed to reorder the 5 instructions as long as the following constraints are met (where x>y means x must be executed before y, or x precedes y):



1 > 3        // cannot increment a before getting the old value
2 > 4 // cannot increment b before getting the old value
1 > 5, 2 > 5 // the sum cannot happen before both temporaries are created


There are no other constraints in the order of execution of the different instructions, so the following are all valid sequences:




1, 2, 3, 4, 5
1, 2, 5, 3, 4
1, 3, 2, 4, 5
...

No comments:

Post a Comment

c++ - Does curly brackets matter for empty constructor?

Those brackets declare an empty, inline constructor. In that case, with them, the constructor does exist, it merely does nothing more than t...