2012-06-08 129 views
2

可能重複的:
Undefined Behavior and Sequence Points評估宏

我有理解下面的宏麻煩:

#define CUBE(x) ((x)*(x)*(x)) 

我的代碼:

int y=5; 
print("Cube = %d",CUBE(++y)); 

這段代碼打印512(使用Microsoft Visual Studio)

我在期待打印:((++5)*(++6)*(++7)) = (6*7*8) = 336
這是如何評估?

同樣的代碼是用Dev C++編譯器編譯的,結果是392!

有人可以解釋爲什麼兩個編譯器顯示完全相同的代碼不同的結果?

++y這個怎麼評估的?

+0

未定義行爲...不要那樣做。 – jn1kk

回答

1

CUBE(++ y));變成(++ y * ++ y * ++ y) - 以什麼順序評估?

要技術 - 它是不確定的,改變功能點之間相同的變量

編輯:見Undefined behavior and sequence points

的Visual C++似乎來評價這是y+=3; y*y*y; so 8*8*8 = 512
382爲7 * 7 * 8,以便開發的C++大概估計第一部分爲y+=2; y*y;然後49*y++

1

在你的表達式中沒有sequence points,所以當副作用(即增量結果ing y)變得可見的是未定義的。簡而言之,在表達式評估完成之前,編譯器可隨時將++y的結果存儲回y

這是製作帶有副作用表達式的宏的危險。用同樣的功能你會更好。

3

當宏被展開時,y的值被修改不止一次而沒有中間順序點。
這是未定義的行爲

未定義行爲意味着任何行爲都是可能的,您的程序不是有效的c程序。
因此,您會在不同的編譯器上看到不同的輸出。

0

預編譯器評估該宏

#define CUBE(x) ((x)*(x)*(x)) 
在你的代碼

int y=5; 
print("Cube = %d",CUBE(++y)); 

int y=5; 
print("Cube = %d",((++y)*(++y)*(++y))); 

寫這樣的代碼混亂,結果是不確定的。

不同的編譯器行爲可能不同。

避免使用這種結構,你不會面臨這樣的問題。

+0

它明確未定義 –

0

我們需要查看代碼(gcc -S.c)的ASM(彙編)以瞭解它究竟發生了什麼。

在開發的C++編譯器ASM看起來像

1)  movl $5, 28(%esp) 
2)  addl $1, 28(%esp) 
3)  addl $1, 28(%esp) 
4)  movl 28(%esp), %eax 
5)  imull 28(%esp), %eax 
6)  addl $1, 28(%esp) 
7)  imull 28(%esp), %eax 

它顯示值5被移動到%尤指(1)中,然後加入兩個時間有(2 & 3),所以現在y的值變爲7;這個值現在被移到eax寄存器(4)並且乘以7 * 7(5);現在給y(6)加1,然後乘以eax;所以答案爲7 * 7 * 8 = 392

在Microsoft Visual Studio這將是8 * 8 * 8