3

可能重复:
未定义的行为和序列点

在机器代码级别的 C++ 中,postincrement++ 运算符何时执行?

优先级表表明 postfix++ 运算符是第 2 级:这意味着在

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

后缀 ++ 的执行。

但是,这行的逻辑操作似乎是先发生加法(0+0),但这是怎么发生的呢?

我想象的如下:

// 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++ 生成的代码被插入到加法运算的下方

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

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

4

4 回答 4

10

我将讨论以下完美的示例,而不是跳到 UB 示例的细节上:

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

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

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

并不是:

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

另一方面,后自增的语义等价于两条单独的指令(从这里开始只是一个心理图景):

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

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

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

但是只要满足以下约束,编译器就可以对 5 条指令重新排序(其中x>y手段x必须在 之前yx之前执行y):

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, 5
1, 2, 5, 3, 4
1, 3, 2, 4, 5
...
于 2011-03-25T15:14:23.687 回答
7

这个

int y = x++ + x++ ;

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

于 2011-03-25T14:35:51.317 回答
4

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

考虑以下:

int x = 0;
int y = x++ + x++;

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

底线是,不要这样做。不会有什么好事。:-)

于 2011-03-25T14:45:03.337 回答
2

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

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

int y = x++ + x++ ;
// First add 0+0
// Increment x
// Increment 

尽管

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

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

于 2011-03-25T14:37:24.833 回答