歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

C/C++中慎用宏(#define)

宏的定義在程序中是非常有用的,但是使用不當,就會給自身造成很大的困擾。通常這種困擾為:宏使用在計算方面。

本例子主要是在宏的計算方面,很多時候,大家都知道定義一個計算的宏,對於編譯和編程是多麼的有用。現在定義有以下一個計算 “乘法” 的宏。

#include <stdio.h>

#define MUL(a) ((a)*(a)*(a))

int main(int argc,char *argv[])

{

int i = 10;

int sum = MUL(i);

printf("MUL(%d) = %d\n",i,sum);

return 0;

}

</stdio.h>

上面程序的這種做法對於非負數而言那就是沒有問題的,比如,程序中的 變量 i=10,這個時候,調用宏得到的數據如下:

但是如何變量的數值是自加或者自減的操作的話,結果就不一樣了。

假如我們將上面的程序變為下面這樣的

#include <stdio.h>

#define MUL(a) ((a)*(a)*(a))

int main(int argc,char *argv[])

{

int i = 10;

int sum = MUL(++i);

printf("MUL(%d) = %d\n",i,sum);

return 0;

}

</stdio.h>

得到的結果並不是 11 * 11 *11 = 1331這個數據,而是 1872,這時候有人會問為什麼?

得到宏的朋友或者了解過宏在計算方面的朋友就會知道,這除了是宏的問題,還是本身程序員編寫這段代碼的問題。當使用了 ++i 和 i++ 的時候,

要特別注意在宏中是全部使用 ++i或者i++的,變成的格式如下

MUL(i++)  ((i++)*(i++)*(i++))

MUL(++i)    ((++i)*(++i)*(++i))

上述的做法顯然不是我們想要的計算結果,可能在我們程序中看到的是MUL(++i) 或者 MUL(i++),認為實際上是如下情況:

//當i的初始化數值為10的時候,進行i++的 MUL(i++)宏計算,即是:int i = 10;

//MUL(i ++)的數值計算結果相比是 10 * 11 * 12的,這是沒有問題的,但是 i的值呢??是11嗎??顯然不是。    MUL(i++) = 10 * 11 *12;i = ??;

  i的數值如下圖所示

誠然,i的數值變成了 13,這是為什麼呢??

那就是因為這個MUL(a)這個宏和程序員的 “自加自減” 操作所造成的。這裡先普及一下 C/C++語言的 “自加自減” 操作:

//自加自減的操作

i++ 和 ++i  ----> 這裡的操作屬於++後操作,可以替換成 i = i+1 的結果。

但是,當它賦值給一個變量的時候,表示的內容和含義就有不同: (假設i = 10)

1.  sum1 = i++;

2.  sum2 = ++i;

1中的sum1的數值就是 10, i為 11

2中的sum2的數值就是 11, i為 11

這是因為:

i++ 操作是 先賦值給 sum1後,自己在執行 i = i+1的操作

++i 操作是 先進行 i = i+ 1的操作,然後再賦值給sum2

這樣得到的結果當然不同了,但是i最終的結果是要加1的,只不過是賦值給變量的時候會有不同

通過對自加自減的操作進行說明,不知道大家是否明白為什麼了嗎??

當 i  = 10的時候,MUL(i++)就是為  (i++)*(i++)*(i++)的計算結果,考慮到C/C++的運算符結合性,先計算第一個 i++,這是一個先計算後賦值的自加方式,那麼這是後第一個 (i++)的數值待定為 10 ,那麼第二個的i是因為第一個數據的 (i++)起了作用而變化的,這時候第二個(i++)的數值為11,然後加1,這時候 根據結合性,先計算前面兩個數據,就是(i++) * (i++)的數值了,即為:10 * 11了,這時候的i數值是 12;然後計算第三個 i++的數值,這時候第三個i++中的i數值為 12,計算後再加1,也就是說,10 * 11 * 12之後,i= 12 的數值在進行i++變為 13了。所以  MUL(i++) = 10 * 11 * 12 = 1320。

另外,在進行++i的操作和上述的情況差不多,只不過是先做自加的運算,在進行賦值。

當 i = 10的時候,MUL(++i)實際上也為 (++i)*(++i)*(++i)的方式,這時候先計算第一個 (++i),這是一個先計算後賦值的結合方式,那麼 i = i+1 = 11;這時候准備計算第二個(++i)的時候,因為需要先計算後賦值,所以 第二個 ++i 之後的數值為12,但是因為i屬於同一個變量和屬性,那麼第一個i也會變成 12了,這時候結合性考慮應該是計算前兩個(++i)的結果,再與第三個(++i)計算,即(++i)*(++i) = 12 * 12;然後,我們計算第三個(++i)的數值,由於前面第二個++i的i值,所以第三個++i即為 13,此時,12 * 12 * 13。

有人可能顧慮,為什麼最後不是13 * 13 * 13的呢?那不是最後都是13嗎??  ------》其實這種想法是錯誤的,這必須先理解運算符的結合性。我們知道,當計算中遇到了括號的時候,我們先計算括號的內容,這是我們在數學中的慣性思維。但是對於計算機而言,計算機必須 有計算的優先級,也就是運算符的優先級問題。首先我們計算前面兩個括號的內容,以為兩個括號之間有乘號(*),所以計算前面兩個(++i)之後,必須進行乘法計算,這就是優先級中的乘法計算,自左向右計算。所以結果變為了 12 * 12的最終結果在和第三個括號的(++i)計算,就是144 * (++ i) = 144 * 13;所以MUL(++i)的結果如下:

總結:

慎用宏在計算方面的,但是宏的有點還是很多的,對於C語言來說,宏可以減少運行的時間。在C++中,宏由於不會對類型進行檢查,安全性不夠,所以建議使用const來

進行使用,這樣可以保證類型一致。這是C/C++對宏的嚴謹性進行優化的結果。更多的宏的知識或者如何定義宏,大家可以上網查查資料。

Copyright © Linux教程網 All Rights Reserved