关于c ++:postincrement i ++什么时候执行?

When does postincrement i++ get executed?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
Undefined Behavior and Sequence Points

在C++代码的机器代码级别,何时执行PoxDeal+++操作符?

优先表指示postfix++运算符是级别2:这意味着

1
2
int x = 0 ;
int y = x++ + x++ ;  // ans: y=0

postfix++首先执行。

然而,这一行的逻辑操作似乎是先进行加法(0+0),但这是如何发生的呢?

我想象的是:

1
2
3
4
5
6
7
8
9
// 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.

所以,另一个选项是,虽然x++在x+x的优先表上更高,但是由于x++生成的代码被插入到加法运算的下面。

1
2
3
4
// Option 2:  turn this into
int y = x + x ; //
x++ ;
x++ ;

第二种选择似乎更有意义,但我对这里的操作顺序感兴趣。具体来说,X什么时候改变?


我将讨论以下非常好的示例,而不是跳到ub示例的细节上:

1
2
int a = 0, b = 0;
int c = a++ + b++;

现在,运算符的优先级意味着最后一行等于:

1
int c = (a++) + (b++);

而不是:

1
int c = (a++ + b)++; // compile time error, post increment an rvalue

另一方面,后增量的语义相当于两个独立的指令(从这里开始只是一个心理图):

1
2
a++; // similar to: (__tmp = a, ++a, __tmp)
     // -- ignoring the added sequence points of , here

也就是说,编译器将原始表达式解释为:

1
2
3
4
5
auto __tmp1 = a;         // 1
auto __tmp2 = b;         // 2
++a;                     // 3
++b;                     // 4
int c = __tmp1 + __tmp2; // 5

但只要满足以下约束条件,编译器就可以对5条指令进行重新排序(其中x>y表示x必须在y之前执行,或者x必须在y之前执行):

1
2
3
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

在执行不同指令的顺序中没有其他约束,因此以下都是有效的序列:

1
2
3
4
1, 2, 3, 4, 5
1, 2, 5, 3, 4
1, 3, 2, 4, 5
...


这个

1
int y = x++ + x++ ;

是未定义的行为。任何事情都可能发生,包括一些不合理的结果、程序崩溃或其他。别那么做。


在C++中有一些叫做"序列点"的东西。如果在没有中间序列点的情况下多次更改值,则行为是未定义的。

考虑以下内容:

1
2
int x = 0;
int y = x++ + x++;

y的值可以是0、1或其他完全随机的值。

底线是,不要这样做。没有什么好结果。-)


在您的情况下,似乎发生了以下情况

当使用x++时,操作完成后,x递增。

1
2
3
4
int y = x++ + x++ ;
// First add 0+0
// Increment x
// Increment

同时

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

但是,不同的编译器将以不同的方式处理它,如果在同一语句中增加两次,应用程序可能会崩溃。