tags:

views:

405

answers:

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?

+4  A: 

Line 3 is undefined, line 5 is not.

EDIT:

As Prasoon correctly points out, both are UB.

The simple expression a + a++ is undefined because of the following:

  1. The operator + is not a sequence point, so the side effects of each operands may happen in either order.
  2. a is initially 1.
  3. One of two possible [sensible] scenarios may occur:

    1. 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.

    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.

Alex
No I think both invoke UB.
Prasoon Saurav
Probably you missed "Furthermore, the prior value shall be read only to determine the value to be stored."
Prasoon Saurav
Oh my. You are right. Both are UB.
Alex
+6  A: 

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++.

John Feminella
You last statement is incorrect. Line 5 also invokes UB.
Prasoon Saurav
Probably you missed "Furthermore, the prior value shall be read only to determine the value to be stored."
Prasoon Saurav
Whoops. You're right! I've fixed this.
John Feminella
+19  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.

Mark Byers
+1, your answer should have been accepted. xD
Prasoon Saurav
+3  A: 

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.

Adam Luchjenbroers
Thx A LOT! xD // that code was just for an educational purpose
Lee Jae Beom
This answer is incorrect because it does not mention "undefined behaviour", which is what you are invoking. The explanation is bogus, too - I am sorry to say. There is no good explanation because the standard says the behaviour is undefined - anything is legitimate.
Jonathan Leffler
Concurrence with Jonathan -- it's not merely that this is "needlessly confusing", but it's actually wrong to do it. The standard does not allow modifying things twice between sequence points.
John Feminella
Updated to reflect that this behavior is undefined. The first sequence of events still adequately explains what happened using his compiler.
Adam Luchjenbroers
@Adam: Giving explanation of an undefined behavior doesn't make much sense. You should have given just the reason why these expressions invoke undefined behavior. Mark's answer is totally correct.
Prasoon Saurav
-1, this is undefined behavior according to the standards, full stop. Giving explanation of such a trivial case out of the umpteen possibilities which themselves are compiler specific is ridiculous
rocknroll
A: 
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.

stakx
The RHS of the second line does not have to evaluate to 2; it could evaluate to 3 if the read of the first-listed 'a' occurs after the increment is complete. The behaviour is undefined and any result is valid.
Jonathan Leffler