后增量运算符:意外行为
我的代码如下:
#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 是想把我从自己的困境中拯救出来吗?我没有方便的语言参考,但我认为这破坏了预期的语义。
Possible Duplicate:
Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)
My code is as follows:
#include <stdio.h>
int main()
{
int x = 10, y = 0;
x = x++;
printf("x: %d\n", x);
y = x++;
printf("y: %d\n", y);
}
Given the nature of post-increment, I would expect the following output:
x: 10
y: 10
My reasoning is that in line 5, x
should be assigned to its initial value after the increment takes place.
Instead, however, I get this:
x: 11
y: 11
Digging into the assembly, this looks like a deliberate choice to me:
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
What's going on here? Is GCC trying to save me from myself? I don't have a language reference handy but I would have thought that this breaks the intended semantics.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
该行为未定义,因为
x = x++
中没有中间序列点,请参见 C 常见问题。The behaviour is undefined as there is no intervening sequence point in
x = x++
, see e.g. the C FAQ.C 语言未定义后置/预置/递减何时发生。因此,诸如
x = x++
之类的语句格式不正确 - 请避免使用它们。It is left undefined by the C language as to when exactly a post/pre-in/decrement occurs. Thus, statements such as
x = x++
are not well formed - avoid them.撇开标准不谈(因为这对于标准来说是未定义的),它的运行方式正是我所期望的。
我的经验法则是,对于包含
x++
的行,将x++
替换为x
并输入x += 1
> 在以下行(或预增量的前一行)。遵循该经验法则,您的代码将写为
Standards aside (since this is undefined with respect to the standard), the way it ran is the way I would have expected it.
My rule of thumb is that for a line with
x++
, you substitutex++
withx
and putx += 1
on the following line (or preceding line for pre-increment).Following that rule of thumb, your code would be written as
当你:
发生的事情是 b 被保存到 a 中,并且在分配完成后 b 增加 1。所以如果你这样做:
并且之前 x 是 10 ,将会发生的情况是 10 将被保存到 x 中,并且之后(在 printf 完成之前)x 将增加 1 到 11。这就是打印 11 的原因。
When you have:
what is happening is that b is saved to a and after the assigment is done b is incremented by one. So if you do:
and previously x was 10 what will happen is 10 will be saved to x and after(before your printf is done) x is incremented by one to 11. That's why 11 is printed.