![](/img/trans.png)
[英]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.