简体   繁体   中英

Question about C programming

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?

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.

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

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM