3

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?

Community
  • 1
  • 1
bobobobo
  • 64,917
  • 62
  • 258
  • 363

4 Answers4

10

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
...
David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
  • This is a very good answer and addresses the question directly. Ty. – bobobobo Mar 25 '11 at 17:08
  • In the example here and OP question you don't / can't get a real surprise though by those order variations. Mentioning examples with undefined / surprise results can tell the relevance of the explanation: e.g. `int i = 0; i = (i++) + (i++);` on gcc (v9) yields `1` in the end. Another compiler, MSVC, yields `2`... – kxr Apr 04 '22 at 13:33
7

This

int y = x++ + x++ ;

is undefined behavior. Anything can happen, including some unreasonable results, program crashing or whatever else. Just don't do that.

Community
  • 1
  • 1
sharptooth
  • 167,383
  • 100
  • 513
  • 979
  • That code does't do what you make think it does, but ... program crashing ? I wouldn't say that. – cprogrammer Mar 25 '11 at 15:00
  • @cprogrammer: The point is, it's undefined behavior. Crashing may not be likely, but it would be allowed. – Fred Larson Mar 25 '11 at 15:06
  • @cprogrammer, @Fred Larson: The key idea here is that you should not waste time thinking of what might happen - http://stackoverflow.com/q/4265736/57428 - you should just not write code like that. – sharptooth Mar 25 '11 at 15:08
4

In C++ there are things called "sequence points". If you alter a value more than once without an intervening sequence point, the behaviour is undefined.

Consider the following:

int x = 0;
int y = x++ + x++;

The value of y could be 0, 1 or some other completely random value.

Bottom line is, don't do it. Nothing good can come of it. :-)

Michael J
  • 7,631
  • 2
  • 24
  • 30
2

In your case, is seems like the following happens

When you use x++, x increments after the operation is complete.

int y = x++ + x++ ;
// First add 0+0
// Increment x
// Increment 

While

int y = ++x + ++x ;
// Add (increment x) and (increment x) = 1+1 = 2

However, different compilers will handle it differently and your application might crash if you increment twice in the same statement.

Phonon
  • 12,549
  • 13
  • 64
  • 114