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; } 

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

        

  可是如何變量的數值是自加或者自減的操做的話,結果就不同了。優化

  假如咱們將上面的程序變爲下面這樣的spa

#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; } 

  獲得的結果並非 11 * 11 *11 = 1331這個數據,而是 1872,這時候有人會問爲何?blog

      

  獲得宏的朋友或者瞭解過宏在計算方面的朋友就會知道,這除了是宏的問題,仍是自己程序員編寫這段代碼的問題。當使用了 ++i 和 i++ 的時候,數學

要特別注意在宏中是所有使用 ++i或者i++的,變成的格式以下io

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的數值以下圖所示class

    

  誠然,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++對宏的嚴謹性進行優化的結果。更多的宏的知識或者如何定義宏,你們能夠上網查查資料。

相關文章
相關標籤/搜索