有一个代码片段,GCC 产生了我没想到的结果:
(我正在为目标 i686-linux-gnu 使用 gcc 版本 4.6.1 Ubuntu/Linaro 4.6.1-9ubuntu3)
[测试.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编译了这个case,结果显示b=5,也就是我所期望的。
我对后增量和序列点行为的理解是否不正确?或者这是 GCC461 的一个已知问题?