[英]Can the post-increment operator be used in the parameters of a function call? in C?
[英]Post-increment, function calls, sequence point concept in GCC
有一个代码片段,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的已知问题?
除了Clang之外,您还可以使用其他两个工具作为参考: Frama-C的价值分析和KCC 。 我不会详细介绍如何安装它们或将它们用于此目的,但它们可用于检查C程序的定义 - 与编译器不同,它们旨在告诉您目标程序是否展示未定义行为。
他们有粗糙的边缘,但他们都认为b
绝对应该是5
,在程序结束时没有未定义的行为:
Mini:~/c-semantics $ dist/kcc ~/t.c
Mini:~/c-semantics $ ./a.out
b = 5
这是一个比Clang更强烈的争论(因为如果它是未定义的行为,Clang仍然可以生成一个打印b = 5
的程序)。
长话短说,看起来你在那个版本的GCC中发现了一个bug。 下一步是检查SVN以查看它是否仍然存在。
我前段时间报告了这个海湾合作委员会的错误,并在今年早些时候修复了。 见http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48814
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.