int k = 1;
printf("%d, %d\n", k++, k++);
#include int func(int i, int j)
int main()
輸出:【gcc】
i = 2, j = 1
3
特別說明:此處暫時沒有找到有其它求值順序的編譯器來輸出說明。
由於c語言未明確規定函式引數的求值順序,其交由具體的編譯器廠商決定,因此為了提高程式的可移植性,不可依賴某一編譯器的求值順序行為。
下面的程式執行結束後 k 的值為多少呢?int k = 2;
k = k++ + k++;
實驗 1
#include int main()
return 0;
}
輸出【gcc】:
k = 6
輸出【vs2010】:
k = 6
vs2010 彙編
k = k++ + k ++;
003d356c mov eax,dword ptr [k]
003d356f add eax,dword ptr [k]
003d3572 mov dword ptr [k],eax ; k = 2 + 2 = 4
003d3575 mov ecx,dword ptr [k]
003d3578 add ecx,1
003d357b mov dword ptr [k],ecx ; k = k + 1 = 4 + 1 = 5
003d357e mov edx,dword ptr [k]
003d3581 add edx,1
003d3584 mov dword ptr [k],edx ; k = k + 1 = 4 + 1 = 6
gcc 彙編
int k = 2;
080483cd: movl $0x2,0x1c(%esp)
k = k++ + k ++;
080483dd: mov 0x1c(%esp),%eax
080483e1: add %eax,%eax
080483e3: mov %eax,0x1c(%esp) ; k = 2 + 2 = 4
080483e7: addl $0x1,0x1c(%esp) ; k = k + 1 = 4 + 1 = 5
080483ec: addl $0x1,0x1c(%esp) ; k = k + 1 = 5 + 1 = 6
實驗 2
#include int func(int i, int j)
int main()
輸出:【gcc】
i = 2, j = 1
3輸出:【用於 80x86 的 microsoft (r) 32 位 c/c++ 優化編譯器 16.00.30319.01 版】
i = 1, j = 1
3
分析:c 檔案會被編譯成彙編檔案。一條c**可能對應多條彙編**,彙編**的順序也許沒有特定的規定。對於不同的編譯器,可能有不同的編譯方式,但都必須滿足這一原則:在程式到達順序點時,所有改變記憶體的操作必須完成。
注意:
在實際工程中, 需要遵循一定的規則避免非 c 語言規定而與編譯器相關的寫法。
對於「函式引數的求值順序」、「程式中的順序點「不必過度深究,遇到奇怪的問題時,思考是否是這裡導致的問題即可。
第44課 函式引數的秘密(上)
1 函式引數在本質上與區域性變數相同,都在棧上分配空間 2 函式引數的初始值是函式呼叫時的實參值 3 c標準只規定了 必須要將每個實參的具體值求出來之後才能進行函式呼叫,並沒有規定函式引數的求值順序,求值順序依賴於編譯器的實現 比如void func 引數表示式1,引數表示式2,引數表示式3 這三個...
main函式引數的秘密
大家應該都有乙個模糊的記憶,c語言中main函式是程式的入口函式,所以程式執行時main函式呼叫別的函式,並且給別的函式傳入引數。但是沒人告訴我們是誰 呼叫 的main函式。其實我們可以理解為是作業系統呼叫的main函式,所以main函式的引數應該是作業系統給的,也就是說我們的在命令列介面執行程式是...
傳入引數個數 main函式引數的秘密
大家應該都有乙個模糊的記憶,c語言中main函式是程式的入口函式,所以程式執行時main函式呼叫別的函式,並且給別的函式傳入引數。但是沒人告訴我們是誰 呼叫 的main函式。其實我們可以理解為是作業系統呼叫的main函式,所以main函式的引數應該是作業系統給的,也就是說我們的在命令列介面執行程式是...