4

The following of post-increments will result as follows:

n = 1;
j = n++;  //j = 1, n = 2
j = n++;  //j = 2, n = 3
j = n++;  //j = 3, n = 4

My question is why the following resulted in n = 1 and not n = 3?

n = 1;
n = n++;  //n = 1
n = n++;  //n = 1
n = n++;  //n = 1

If the code was done with pre-increment of n (++n), the result is n = 4 which is to be expected. I know the second code segment should never be done like that in the first place but it is something that I came across and I was curious as to why it resulted like that.

Please advise.

Niall
  • 30,036
  • 10
  • 99
  • 142
user3531168
  • 309
  • 3
  • 11
  • 7
    Your statement `n = n++;` results in undefined behaviour. What you are seeing is the value before the increment being assigned back to `n`. – Niall Oct 06 '14 at 08:03
  • In C++03 this was Undefined Behavior (modifying a variable twice between sequence points). In C++11, as I recall, it was changed to well-defined. Lemme look it up. – Cheers and hth. - Alf Oct 06 '14 at 08:03
  • 3
    @Cheersandhth.-Alf IIRC, the edge-cases all involve pre-icrement, like `i = ++i;`, because the evaluation of LHS and RHS (which includes increment of `i`) is sequenced before the assigment. In `i = i++;`, the increment is still unsequenced relative to assignment and therefore still UB. – jrok Oct 06 '14 at 08:09
  • 1
    @Cheersandhth.-Alf Still undefined: 1.9/15 "If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined." – Angew is no longer proud of SO Oct 06 '14 at 08:13
  • 1
    @Angew This is what I never quite understood about this - it's true that assignment is sequenced after the evaluation of operands, but the evaluations of operands are still unsequenced. Even [CWG defect 637](http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#637), for example, seems to completely disregard 1.9/15. – jrok Oct 06 '14 at 08:23
  • this **must** be a duplicate – Galik Oct 06 '14 at 08:39
  • I always wonder why people write `n = n++` and expect something sane to come out of it. If you want to increment `n`, then use `n++`. If you want `n` to stay the same, then just delete the line. – Raymond Chen Oct 06 '14 at 19:55
  • Thank you for the feedback. @RaymondChen: I wonder the same thing too but I was just curious as to why I gotten that result when trying it out after looking through someone else's code. – user3531168 Oct 07 '14 at 02:07

3 Answers3

10

Your second example is not allowed and has an undefined behaviour. You should use a temporary variable if you need something like that. But hardly you need something like that.

Quoting Wikipedia:

Since the increment/decrement operator modifies its operand, use of such an operand more than once within the same expression can produce undefined results. For example, in expressions such as x − ++x, it is not clear in what sequence the subtraction and increment operators should be performed. Situations like this are made even worse when optimizations are applied by the compiler, which could result in the order of execution of the operations to be different from what the programmer intended.

dynamic
  • 46,985
  • 55
  • 154
  • 231
  • 2
    or quoting [stack overflow](http://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points) – o11c Oct 06 '14 at 08:08
3

Other examples from C++11 standard include:

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
f(i = -1, i = -1); // the behavior is undefined
Unihedron
  • 10,902
  • 13
  • 62
  • 72
Laura Maftei
  • 1,863
  • 1
  • 15
  • 25
1

The other answers explain correctly that this code results in undefined behaviour. You may be interested as to why the behaviour is as you see it on your compiler.

As far as most compilers are concerned the expression x = n++ will be compiled into the following fundamental instructions:

  1. take a copy of n, call it n_copy;
  2. add 1 to n
  3. assign n_copy to x

Therefore the expression n = n++ becomes:

  1. take a copy of n, call it n_copy;
  2. add 1 to n
  3. assign n_copy to n

Which is logically equivalent to:

  1. assign n to n

Which is logically equivalent to:

  1. do nothing.

That's why in your case you see n == 1. Not all compilers will necessarily produce the same answer.

Richard Hodges
  • 68,278
  • 7
  • 90
  • 142