2013-01-21 64 views
2

可能重複:
Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)
What problems might the following macro bring to the application?混亂與宏擴展

我寫了一個示例應用程序宏展開在我的iOS實現它(目標C代碼)。

它是這樣的:

#define SQUARE(x) (x * x) 
main() 
{ 
    int i = 3, j, k ; 
    j = SQUARE(i++) ; 
    k = SQUARE(++i) ; 
    printf ("\nValue of i++ = %d\nValue of ++i = %d", j, k) ; 
} 

產量爲:

Value of i++ = 9 
Value of ++i = 49 

預計產量爲:

Value of i++ = 9 
Value of ++i = 25 

我對這個結果感到驚訝。我對這個宏觀擴張有點困惑。

爲什麼發生?請幫我找出原因。

+0

我想你可以通過寫'#define SQUARE(x)((0,x)*(0,x))來修復代碼,它引入了一個序列點。你應該在每個宏參數中總括_括號,以避免錯誤。但清醒而明智的解決方案是不使用類似於函數的惡意宏,並始終將++運算符保留在自己的行上。 – Lundin

回答

6

這確實是不確定的行爲(且不應被另一個編譯器,甚至相同的編譯器的下一次運行依賴於),因爲它在相同的語句中增加同一個變量兩次而沒有序列點,但這是在這種情況下似乎發生的事情;

#define SQUARE(x) (x * x) 
j = SQUARE(i++) ; 
k = SQUARE(++i) ; 

將擴大到

j = (i++ * i++);  // Compiler could do i * i, then increment twice, or use i * (i + 1), or... 

k = (++i * ++i);  // Same as above 

由於這是不確定的行爲,編譯器可以自由地爲所欲爲(GCC的舊版本製作的節目推出nethack ;-)。更確切地說:編譯器可以自由地假定永遠不會調用未定義的行爲,只要確保代碼在「正常」情況下正常工作即可。在意想不到的情況下會發生什麼是任何人的賭注。

+0

+1的答案。 –

+1

UB不能有任何解釋。一旦UB被調用,沒有人知道編譯器將會表現/評估。 –

+0

感謝您的回答:) –

6

您正在調用未定義的行爲通過修改i多次而沒有中間順序點。

馬可孛subsitution後,兩線將是這樣的:

j = (i++ * i++) ; 
    k = (++i * ++i) ; 
+0

感謝您的回答:) –

1

這是因爲您正在兩個序列點之間遞增兩次單個變量。因此這是一個未定義的行爲

int i = 3, j, k ; 
    j = SQUARE(i++) ; // it becomes (i++ * i++) 
    k = SQUARE(++i) ; // it becomes (++i * ++i) 

因此輸出來的是未定義的。

你得到的輸出是因爲在第一個表達式之後,我要遞增兩次 所以在secon表達式中,由於預先遞增,我得到了兩次遞增,它也得到兩次遞增。

j=(i++ * i++)//it comes 3*3 

k=(++i * ++i)// it comes 7 as two increments of above xpression