【发布时间】:2012-08-11 14:33:48
【问题描述】:
有一段代码是GCC产生了我没想到的结果:
(我使用 gcc 版本 4.6.1 Ubuntu/Linaro 4.6.1-9ubuntu3 用于目标 i686-linux-gnu)
[test.c]
#include <stdio.h>
int *ptr;
int f(void)
{
(*ptr)++;
return 1;
}
int main()
{
int a = 1, b = 2;
ptr = &b;
a = b++ + f() + f() ? b : a;
printf ("b = %d\n", b);
return a;
}
在我的理解中,函数调用有一个序列点。 后增量应在 f() 之前进行。
参见 C99 5.1.2.3: “......称为序列点,之前评估的所有副作用 应完整且后续评估无副作用 已经发生了。”
对于这个测试用例,可能评估的顺序是未指定的, 但最终的结果应该是一样的。所以我希望 b 的最终结果是 5。 但是,在使用 'gcc test.c -std=c99' 编译此案例后,输出显示 b = 3。
然后我使用“gcc test.c -std=c99 -S”看看发生了什么:
movl $1, 28(%esp)
movl $2, 24(%esp)
leal 24(%esp), %eax
movl %eax, ptr
movl 24(%esp), %ebx
call f
leal (%ebx,%eax), %esi
call f
addl %esi, %eax
testl %eax, %eax
setne %al
leal 1(%ebx), %edx
movl %edx, 24(%esp)
testb %al, %al
je .L3
movl 24(%esp), %eax
jmp .L4
.L3:
movl 28(%esp), %eax
.L4:
movl %eax, 28(%esp)
似乎 GCC 在 f() 之前使用评估值并执行 '++' 两次 f() 调用后的操作。
我也使用llvm-clang来编译这个案例, 结果显示 b = 5,这是我所期望的。
我对后增量和序列点行为的理解不正确吗? 或者这是 GCC461 的一个已知问题??
【问题讨论】:
-
欢迎来到 StackOverflow!请不要对可能想复制粘贴学习的程序行编号。
-
哦~好的!现在我已经删除了程序的行数。谢谢提醒! :)
标签: c c99 gcc4 sequence-points