2012-03-24 56 views
0

我不明白爲什麼結果將是36.有人可以向我解釋這裏發生了什麼,以及預處理器做了什麼?C++宏的副作用

#include <iostream> 
#define QUADRAT(x) ((x) * (x)) 

using namespace std; 

int main() 
{ 
    double no = 4.0; 
    double result = QUADRAT(++no); 

    cout << result; 
    return 0; 
} 

非常感謝:>

回答

4

在該示例中,預處理器將用((++no) * (++no))代替QUADRAT(++no)

如果不是因爲兩個增量之間沒有順序點這一事實,會增加兩次no,所以實際上會導致未定義的行爲。你看到的任何輸出都是有效的,因爲沒有人能夠知道會發生什麼。

+1

感謝奧利,現在它有道理:) – Max 2012-03-25 00:00:46

2

預處理是基本上是複製和粘貼引擎。注意一個宏是而不是的一個函數;相反,它是內嵌擴展的。考慮在擴展宏時代碼會發生什麼。

+2

塞思,我想他說了一個錯誤的答案。 – 2012-03-25 00:01:47

+0

我的意思是你的回答Seth,但奇怪的是Stackoverflow告訴我這是Oli的錯誤發佈。現在你的名字是在它下面..:/ – Max 2012-03-25 00:09:50

0

會發生什麼事是一種替代X的++沒有文字替代的,這就像你寫的:

double result = ((++no) * (++no)); 

的結果是什麼?應該是不確定的行爲(你36偶然),並且g ++與-Wall同意我的觀點。

1

這條線:

double result = QUADRAT(++no); 

被擴大到這一點:

double result = ((++no) * (++no)); 

,這最終運行的方式是等價於:

no = no + 1; 
no = no + 1; 
result = no * no; 

它運行這種方式,因爲增量在乘法之前執行:預處理器做一個你傳遞它的文本副本,所以它複製「++ no」,以便在最終代碼中顯示兩次,並且在計算結果之前每個++的增量不發生。解決這個問題的方法是使用一個內聯函數:

inline double QUADRAT(double x) { return x * x; } 

大多數現代編譯器會出擴大這個代碼,而不做一個文本替換 - 他們會給你的東西一樣快,預處理器定義,但沒有危險像你面臨的問題一樣。