9

可能重复:
谁能解释这些未定义的行为(i = i++ + ++i,i = i++ 等……)

我的代码如下:

#include <stdio.h>
int main()
{
  int x = 10, y = 0;
  x = x++;
  printf("x: %d\n", x);
  y = x++;
  printf("y: %d\n", y);
}

鉴于后增量的性质,我希望得到以下输出:

x: 10
y: 10

我的理由是,在第 5 行中,x应该在增量发生后将其分配给它的初始值。

然而,相反,我得到了这个:

x: 11
y: 11

深入研究程序集,这对我来说似乎是一个深思熟虑的选择:

LCFI2:
        movl    $10, -4(%rbp)   // this is x
        movl    $0, -8(%rbp)    // this is y
        incl    -4(%rbp)        // x is simply incremented
        movl    -4(%rbp), %esi
        leaq    LC0(%rip), %rdi
        movl    $0, %eax
        call    _printf
        movl    -4(%rbp), %eax  // now x is saved in a register,
        movl    %eax, -8(%rbp)  // copied to y,
        incl    -4(%rbp)        // and finally incremented
        movl    -8(%rbp), %esi
        leaq    LC1(%rip), %rdi
        movl    $0, %eax
        call    _printf

这里发生了什么?GCC 是想把我从自己身边救出来吗?我没有方便的语言参考,但我认为这会破坏预期的语义。

4

4 回答 4

13

该行为是未定义的,因为没有中间的序列点x = x++,请参见例如C FAQ

于 2010-07-19T02:25:49.093 回答
4

C 语言未定义确切的后/前/减量发生时间。因此,诸如此类的陈述x = x++格式不正确 - 避免使用它们。

于 2010-07-19T02:22:02.020 回答
2

抛开标准不谈(因为这在标准方面是未定义的),它的运行方式是我所期望的。

我的经验法则是,对于带有 的行x++,您替换x++x并放在x += 1下一行(或前一行作为预增量)。

根据该经验法则,您的代码将被编写为

#include <stdio.h>
int main()
{
  int x = 10, y = 0;
  x = x; // x: 10
  x += 1; // x: 11
  printf("x: %d\n", x);
  y = x; // y: 11
  x += 1; // x: 12
  printf("y: %d\n", y);
}
于 2010-07-19T02:42:13.030 回答
1

当你有:

a = b++;

发生的事情是 b 被保存到 a 并在分配完成后 b 加一。所以如果你这样做:

x = x ++;

之前 x 是 10 将会发生的事情是 10 将被保存到 x 之后(在你的 printf 完成之前)x 增加 1 到 11。这就是打印 11 的原因。

于 2010-07-19T02:23:40.847 回答