C語言函式引數中的表示式順序問題

2021-06-22 13:26:28 字數 2063 閱讀 3939

偶然一次遇到乙個c程式,**如下:

#include int main()

不知為何,大家在討論這個問題的時候出現了分歧,有人說程式輸出的是0,0,也有人說程式輸出的是0,-1。這個問題,執行試試不就知道了嗎,搞得這麼複雜。

結果,不看不知道,一看嚇一跳。gcc編譯之後會輸出0,0,vs2013下得到的結果卻是0,-1,。這,未免有點兒嚇人。這引起了我極大的興趣,按理說,函式引數的表示式計算的順序預設應該是從右往左;比如:

fun(f1(),f2());
這樣的**,f2會先被呼叫,其次是f1。而遇到逗號表示式

a=(f1(),f2());
這樣的東西時,預設應該是先執行f1,然後是f2。最後a的值取f2的返回值。

這樣的話,在gcc中就能解釋的通了,先計算b-1得到0,作為引數傳入printf,然後,計算(a++,--b),注意這時候b的值是1,所以(a++,--b)的值也是0。因此printf輸出0,0。

但是在vs中卻出現了不同的結果,輸出了0,-1。滿懷好奇心的我開啟了vs的除錯,進入了反彙編。

6: 	printf("%d,%d\n", (a++, --b), b - 1);

004153cc mov eax,dword ptr [a]

004153cf add eax,1

004153d2 mov dword ptr [a],eax

004153d5 mov ecx,dword ptr [b]

004153d8 sub ecx,1

004153db mov dword ptr [b],ecx

004153de mov edx,dword ptr [b]

004153e1 sub edx,1

004153e4 push edx

004153e5 mov eax,dword ptr [b]

004153e8 push eax

004153e9 push 436dc0h

004153ee call _printf (0412b6dh)

004153f3 add esp,0ch

為便於閱讀,筆者開啟了符號顯示。我們可以看到,在vs2013中,先執行了a++,然後是--b,然後才是將b-1送入printf!!!

這個問題變得複雜起來了,如果函式有多個引數,每個引數都含有逗號表示式。想到這裡,筆者不禁一陣冷汗。算了,試試吧。

於是筆者寫下這樣的**:

#include int f(int x)

int main()

gcc編譯後輸出的結果是這樣的: 

45623

3 6

而vs2013中卻輸出了這樣的結果:

45263

3 6

順序不一樣!!!到了這裡筆者已經不想再折騰,我想讀者你也應該已經看到,在gcc和vs中各表示式依次執行的順序。

不知道細心的讀者是否注意到了,以上的**在vs中出現了衝突(對比第乙個**和第二個**在vs中的執行順序,你會發現兩者不一致!!)。筆者已不想再折騰,就簡單說一下gcc中總結的結果吧。gcc中,是按照函式引數從右至左,逗號表示式中從左至右的順序執行的。並且逗號表示式的值為最右邊的表示式的值。而在vs中,逗號表示式的取值方式依然沒有變化,但是執行的順序卻十分奇怪。

在這裡,筆者想要說明的就是,在實際寫**的過程中,千萬不要裝x寫這樣的作死的**,可移植性有待考究。在不同的編譯環境下得到了不一樣的結果,這在實際程式設計中是不能被接受的。

當然,這樣的問題也不止乙個,總之,筆者的建議,盡量寫標準,規範,可讀性高,可移植性好的**。一句話:「裝x一時爽,除錯火葬場」。

謝謝。

c 表示式求值順序

今天寫了乙個搜尋函式,碰到了乙個有關表示式求值順序的bug,看下面兩段 這是為乙個向量寫的乙個搜尋函式,輸入乙個值,然後返回這個值在向量中的秩rank,如果該值在向量中存在多個,返回最大的,找不到返回 1 template rank yvector find const t e const temp...

中序表示式轉為後序表示式(c語言)

按照中序表示式與後序表示式的規則借助堆疊進行表示即可 後附詳細鏈結二叉運算樹 中序表示式就是我們在數學中見到的中規中矩的表示式,例如3 2 2 3 7 後序表示式滿足運算符號置於數字的後面 在轉化的過程中滿足的規則 講解 include include include define maxsize ...

c語言表示式的運算順序

c語言中表示式的運算順序由優先順序和結合性決定。1.先按運算子優先順序運算。2.如果相鄰若干個運算子優先順序相同,則按結合方向來運算。比如 1 2 3 4的運算為 有優先順序先做 運算,3 4得到12 表示式為1 2 12,算數運算子為從左到右的結合方向,即先做 運算,再做 運算。下面是c語言運算子...