2011-04-27 69 views
9

的命令,但我不明白這一點:ç預處理器和我學習C這樣的操作

#define square(x) x*x 
a = square(2+3) //a = 11 

當這個運行時,爲什麼a最終被11

+10

就像一個忠告,這個例子顯示的很多原因,你應該避免使用宏在C,直到有一天,你在哪裏一個* *真的**知道你在做什麼。當然,當那一天到來時,你會知道爲什麼要詳細地避免它們... – 2011-04-27 16:13:30

+0

@ T.E.D .:宏(和一般的預處理器)是一個類似於任何其他工具的工具。這個例子並沒有說明爲什麼你不應該使用宏 - 它只是顯示了一個不適用的特殊用例。宏的好用和壞用都有。 – 2011-04-27 16:21:07

+2

也就是說,當然有更多壞的用途比好的:) – 2011-04-27 16:21:26

回答

21

它擴大到2+3*2+3,相當於2+(3*2)+3。使用括號來修復它:

#define square(x) ((x)*(x)) 

現在有了square(x++)嘗試一下,你會碰到更多的問題(未定義行爲)。如果可以的話,避免將它作爲宏來執行。

+3

等效的C++函數應該和宏一樣有效(在優化出現的現代編譯器上)並且不會受到這個影響問題。 – 2011-04-27 16:09:05

+2

@Martin:正確,如果OP使用C++。適應症是它可能是C.我認爲C99也有內聯函數,它似乎是GNU C中的擴展。http://en.wikipedia.org/wiki/Inline_function#Language_support – 2011-04-27 16:12:02

12

square(2+3)擴展到2+3*2+3這相當於2+(3*2)+3 [*的優先級高於+]

海合會可以使用-E選項來查看您的預處理器產生什麼

C:\Users\SUPER USER>type a.c 
#define square(x) x*x 

int main() 
{ 
    a = square(2+3); //a = 11 
} 

C:\Users\SUPER USER>gcc -E a.c 
# 1 "a.c" 
# 1 "<built-in>" 
# 1 "<command-line>" 
# 1 "a.c" 


int main() 
{ 
    a = 2+3*2+3; 
} 

補救

試試這個

#define square(x) ((x)*(x)) 
+0

感謝您的提示,我將使用-E :) – jhon 2011-04-27 16:43:57

+0

+1不僅可以發現問題,還可以教導OP(以及我們其他人)如何調試這些問題。 – Heinzi 2011-04-28 14:49:41

1

因爲2 + 3在表達x * x字面上取代,它變得2 + 3 * 2 + 3*操作具有更高的優先級,所以你沒有得到預期的結果。

務必附上宏參數和整個括號中的表達式,以避免這種情況:

#define SQUARE(x) ((x) * (x)) 

另外請注意,您通過任何表達都需要進行兩次評估,如果表達式有副作用,這樣可以不希望作爲分配或函數調用。在這些情況下,最好使用內聯函數。

+2

總是也將括號括在括號中。根據你的建議,'1.0/square(x)'將被評估爲'1.0 /(2 + 3)*(2 + 3)',因此'1.0'而不是'0.04'。 – 2011-04-27 16:11:16

+0

@Sam:採取的措施。具有諷刺意味的是,但我自己曾經說過幾個月前在這個答案:http://stackoverflow.com/questions/4455307/weird-macro-definition-issue/4455354#4455354 – 2011-04-27 16:12:59

1

嘗試:

#define square(x) ((x)*(x)) 
0

想想你得到什麼,當宏展開。 c預處理器將擴展爲

a = 2 + 3 * 2 + 3 

您需要正確定義您的宏。始終將宏變量括在括號中。這會給你預期的結果。

#define square(x) ((x)*(x)) 

宏擴展會是這樣:

a = ((2 + 3) * (2 + 3)) 
+0

你的建議是不「正確定義」的宏。 1.0/square(x)'將被評估爲'1.0 /(2 + 3)*(2 + 3)',因此'1.0'而不是'0.04'。 – 2011-04-27 16:10:07

+0

我修復了錯誤定義的宏。增加了另一套括號。 – don 2011-04-27 16:12:41