標籤:

關於c前置,後置++,及函數傳參的問題?

如下一段代碼:

#include &

int funadd (int a, int b) {

return 2 * a + 3 * b;

}

int main()

{

int index = 1;

int c = funadd(++index, ++index);

printf("%d
", c);

index = 1;

c = funadd(index++, index++);

printf("%d
", c);

index = 1;

c = funadd(index++, index);

printf("%d
", c);

index = 1;

c = funadd(index, index++);

printf("%d
", c);

scanf("%d", c);

}

輸出:

使用GCC以及VS2015自帶編譯器的輸出皆為:

15

7

8

7

按照我的理解,第一個調用相當於funadd(2, 3)=13,第二個相當於funadd(1, 2)=8,第三個相當於funadd(1, 2)=8,第三個相當於funadd(1, 1) = 5.

實際的輸出是否是由於指令重拍以及傳參順序等引起的?

/*******補充**********/

其實問題來源於工作中我寫的一段與此類似的代碼,發現有問題之後才做的這些測試,代碼類似如下:

class TestClass {

public:

int x;

int y;

TestClass(int a, int b) {

x = a;

y = b;

}

void getvalue() {

cout &<&< "[" &<&< x &<&< " " &<&< y &<&< "]" &<&< endl;

}

};

int main()

{

int *data = (int *)malloc(sizeof(int) * 6);

for (int i = 0; i &< 6; ++i)

{

*data++ = i;

}

data -= 6;

vector& veccc;

for (int i = 0; i &< 3; ++i)

{

TestClass tc(*data++, *data++);

tc.getvalue();

}

free(data-6);

}

其輸出為:

[1 0]

[3 2]

[5 4]

我期望的輸出為:[0 1] [2 3] [4 5]。

我做了一些測試,有如下規律:如果是兩個前置++,那麼就好像兩個++操作都會被「重排」到傳參之前,即傳入的是(index+2, index+2);如果是兩個後置++操作,那麼第二個參數就會優先處理,而第一個參數則是因為++的作用而加1,相當於傳入的是(index+1, index)。

我不懂彙編,是否能有大大有空幫忙看看彙編是啥情況,感激不盡!


具體到這個例子,兩個參數的求職順序可以先左後右或者先右後左,後置++可以在index++求值到遇到分號之間的任何時候執行,所以不同的編譯器、同一個編譯器的不同配置(如debug和release)、還有跟人腦有不同的結果是正常的。


未定義行為。

理論上來講,編譯器可以把代碼編譯成在此時故意立即格式化你的硬碟,也是符合語言標準的。


建議你不要依賴或過度考慮參數求值順序。

C 和 C++17 前的函數參數求值是無序 (unsequenced) 的。上面代碼涉及到對標量對象的無序的兩次寫入或無序的讀和寫,產生未定義行為(允許崩潰)。

而 C++17 起函數參數求值變為不確定順序 (indeterminately sequenced) ,使用哪種順序是未指定的。儘管上面這些代碼在 C++17 中合法,但仍然有不可預測的行為,包括不同位置的行為可以不同。


推薦閱讀:

已經不在學校了,在軟體專業上,該怎麼制定學習的策略?
國內哪一家公司的編譯隊伍技術最高?
typeid如何得出變數的類型?
最好的編譯器課程
動手寫一門簡單語言吧喵 從計算姬開始

TAG:編譯原理 | CC |