int a, b;
a = 1;
a = a + a++;
a = 1;
b = a + a++;
printf("%d %d, a, b);
output : 3,2
What's the difference between line 3 and 5?
int a, b;
a = 1;
a = a + a++;
a = 1;
b = a + a++;
printf("%d %d, a, b);
output : 3,2
What's the difference between line 3 and 5?
Line 3 is undefined, line 5 is not.
As Prasoon correctly points out, both are UB.
The simple expression a + a++
is undefined because of the following:
+
is not a sequence point, so the side effects of each operands may happen in either order.a
is initially 1
.One of two possible [sensible] scenarios may occur:
The first operand, a
is evaluated first,
a) Its value, 1
will be stored in a register, R
. No side effects occur.
b) The second operand a++
is evaluated. It evaluates to 1 also, and is added to the same register R
. As a side effect, the stored value of a
is set to 2.
c) The result of the addition, currently in R
is written back to a
. The final value of a
is 2.
The second operand a++
is evaluated first.
a) It is evaluated to 1
and stored in register R
. The stored value of a
is incremented to 2
.
b) The first operand a
is read. It now contains the value 2
, not 1
! It is added to R
.
c) R
contains 3
, and this result is written back to a
. The result of the addition is now 3
, not 2
, like in our first case!
In short, you mustn't rely on such code to work at all.
What you're doing on line 3 is undefined. C++ has the concept of "sequence points" (usually delimited by semicolons). If you modify an object more than once per sequence point, it's illegal, as you've done in line 3. As section 6.5 of C99 says:
(2) Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored.
Line 5 is also undefined because of the second sentence. You read a
to get its value, which you then use in another assignment in a++
.
What you are doing is undefined.
You can't change the value of a variable you are about to assign to.
You also can't change the value of a variable with a side effect and also try to use that same variable elsewhere in the same expression (unless there is a sequence point, but in this case there isn't). The order of evaluation for the two arguments for + is undefined.
So if there is a difference between the two lines, it is that the first is undefined for two reasons, and line 5 is only undefined for one reason. But the point is both line 3 and line 5 are undefined and doing either is wrong.
a++
is a post-fix operator, it gets the value of a then increments it.
So, for lines 2,3:
a = 1
a = 1 + 1, a is incremented.
a becomes 3 (Note, the order these operations are performed may vary between compilers, and a can easily also become 2)
for lines 4,5:
a = 1
b = 1 + 1, a is incremented.
b becomes 2, a becomes 2. (Due to undefined behaviour, b could also become 3 of a++ is processed before a)
Note that, other than for understanding how postfix operators work, I really wouldn't recommend using this trick. It's undefined behavior and will get different results when compiled using different compilers
As such, it is not only a needlessly confusing way to do things, but an unreliable, and worst-practice way of doing it.
EDIT: And has others have pointed out, this is actually undefined behavior.
a = 1
a = a + a++;
After the first line, a
will have a value of 1. The right-hand side of the second line evaluates to 2. This value is then stored back into variable a
, and at the same time a
is incremented. But it's not clear whether a
gets increased before or afterwards. Therefore the strange result. I wouldn't bet on it that this program would always give the above result, on any machine with any compiler.