天天看點

#define宏定義的陷阱

我們知道,#define是C/C++中用于宏定義的,一般的了解就是直接将其在程式中替換掉。具體什麼的就不多說了,主要說說容易出錯的幾個點:(筆者也是在各種打擊中偶然收獲的)

題1:下面題目的答案是?(填空題)

#define  SQUARE(x)  x*x
則 SQUARE( 1+1)的值是多少?
           

解析:估計大家初學C/C++都會被這樣的題坑過,大緻思路是SQUARE(1+1) == SQUARE(2)==2*2 ==4,于是答案為4.這是最低級的錯誤,錯在哪裡很容易就能看的出。因為計算機處理的時候,隻是簡單的替換,是以,SQUARE(1+1)==1+1  *  1+1==1+1+1 ==3(乘法的優先級高于加法),是以這題的答案是 3 ,而不是4.

但是,如果将題目改成下面這樣:

#define  SQUARE(x)  ( x)*(x)
則 SQUARE( 1+1)的值是多少?
           

注意觀察改動的地方,僅僅是添加了兩個括号。但是,就是這兩個括号使得答案變了,SQUARE(1+1) == (1+1)*(1+1)==2*2 ==4,是以答案就是簡單的4.

好了,有了上面題目和變種題的鋪墊,我們看下面一個題目:

題2:下面題目的答案是什麼?(自己先想想,答案在頁面的最底端)

#define  SQUARE(x)  x*x
則 SQUARE( SQUARE(1+1))*2的值是多少?
           

(A) 6           (B) 10       (C) 18      (D)32

解析:是不是可以這樣想呢?借用上一題的答案SQUARE(1+1) ==3,是以将3代替SQUARE(1+1),就有SQUARE(SQUARE(1+1))*2==SQUARE(3)*2==3*3*2==18,剛好發現答案的選項中有一個18,好開心哦。錯!錯!錯!錯在哪裡?錯在借用了上一題的答案,宏定義不是函數,不能随便借用的。

隻能一步一步的替換,SQUARE(SQUARE(1+1))*2 == SQUARE(1+1*1+1)*2==1+1*1+1*1+1*1+1*2==6,很意外,對吧。不信在機器上試試。

題3:也是一道很詭異的題目。

#define PRINTF(a);   printf("#")
int main( )
{
int a = 0;
for(int i=0;i<5;++i)
   PRINTF(a+i);
system("pause");
return 0;
}
           

這題乍一看,也是一個簡單的字元串替換的遊戲。PRINTF(a);無論括号裡的數字是多少,都替換成printf("#")    由于循環了5次,是以程式會連續輸出5個 #,機器上試試才發現完全不是那麼回事。怎麼回事?仔細看宏定義!細心的你也許看到了詭異的地方,就是宏定義的時候分号的位置!

在機器上運作發現,程式的結果是輸出一個 # 

原來,在宏定義中,直接将#define  PRINTF(a);    printf("#")  解釋成  #define  PRINTF(a)      ;printf("#")  【注意寫法的不同,空格的位置】

也就是說上述程式中,循環體中的語句為空,替換之後結果為:

for(int i=0;i<5;++i)
   ;printf("#");
           

這樣一來,輸出的結果就很明了了。輸出一個#