偶然一次遇到乙個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語言運算子...