2015-02-10 96 views
0

我試圖瞭解cdecl調用約定,我偶然發現了這種奇怪的行爲。試圖瞭解參數的評估(如果涉及一些算術運算)傳遞給函數

根據cdecl標準,調用函數將參數從右到左存儲到堆棧,然後調用目標函數。所以我假設參數將從左到右進行評估,因爲這將看起來像是一個堆棧流,或者它仍然可以從右到左進行評估,因爲存儲參數的規定是cdecl

但下面的程序輸出讓我感到困惑。以下是我爲了解參數評估而編寫的簡單程序。

void fun (int a, int b, int c) {  
    printf("a: %d, b: %d, c: %d\n", a, b, c); 
}  

int main()  
{ 
    int i = 2; 
    fun(i, i++, i); 
} 

預期輸出:a: 3, b: 2, c: 2 or a: 2, b: 2, c: 3

實際輸出:a: 3, b: 2, c: 3

gcc --version 
gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2 
Copyright (C) 2013 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

有人可以拋出一些光對此有何看法?

+1

查看其他的問題,它清楚地解釋了爲什麼「存儲從從右到左參數」是完全無關的計算順序。 – 2015-02-10 05:09:59

+0

無論評估或參數存儲問題的順序如何,此代碼都會導致未定義的行爲(由於「i」和「i ++」的混合)[請參閱此處](http://stackoverflow.com/questions/949433/why-are -these-constructs-using-undefined-behavior) – 2015-02-10 06:28:32

回答

0

這是一個普遍的困惑:有兩個一元運算符遞增一個數字:var++++varvar++將在之後向變量加1,將該變量的值傳遞給函數,而++var將在之前加上一個,數據被傳遞給函數。

嘗試更改++運算符的位置,看看會發生什麼。

簡單的例子:

#include <iostream> 
int main() { 
    int i = 5; 
    std::cout << i << std::endl; //Prints "5" 
    std::cout << i++ << std::endl; //Also prints "5", but after i is 6 
    std::cout << ++i << std:: endl; //Prints "7" 
+0

我將它改爲fun(i,i,i ++);我得到了下面的輸出。a:3,b:3,c:2。這對我來說是有意義的,因爲我可以斷定評估發生在右至左。但是在前一種情況下,它是模糊的。 – VinKris 2015-02-10 05:02:11

+0

不一定「在代碼行結束後」。簡單地說,「後增量的價值就是變量的舊價值」。 – 2015-02-10 05:04:11

+1

現在,你鼓勵使用未定義的行爲:( – 2015-02-10 05:04:34