#define是c語言中提供的巨集定義命令,其主要目的是為程式設計師在程式設計時提供一定的方便,並能在一定程度上提高程式的執行效率,但學生在學習時往往不能 理解該命令的本質,總是在此處產生一些困惑,在程式設計時誤用該命令,使得程式的執行與預期的目的不一致,或者在讀別人寫的程式時,把執行結果理解錯誤,這對 c語言的學習很不利。
巨集的定義在程式中是非常有用的,但是使用不當,就會給自身造成很大的困擾。通常這種困擾為:巨集使用在計算方面。
本例子主要是在巨集的計算方面,很多時候,大家都知道定義乙個計算的巨集,對於編譯和程式設計是多麼的有用。現在定義有以下乙個計算 「乘法」 的巨集。
#include
#define mul(a) ((a)*(a)*(a))
int main(int argc,char www.cppcns.com*ar**)
上面程式的這種做法對於非負數而言那就是沒有問題的,比如,程式中的 變數 i=10,這個時候,呼叫巨集得到的資料如下:
但是如何變數的數值是自加或者自減的操作的話,結果就不一樣了。
假如我們將上面的程式變為下面這樣的
#include
#define mul(a) ((a)*(a)*(a))
int main(int argc,char *ar**)
得到的結果並不是 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。ulydlrpgss
另外,在進行++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++對巨集的嚴謹性進行優化的結果。
本文標題: c/c++中巨集定義(#define)
本文位址: /ruanjian/c/179480.html
define巨集定義中的 ,
1 stringizing 字串化操作符 其作用是 將巨集定義中的傳入引數名轉換成用一對雙引號括起來引數名字串。其只能用於有傳入引數的巨集定義中,且必須置於巨集定義體中的引數名前。如 define example instr printf the input string is t s n inst...
define巨集定義中的 , , ,
巨集只能放在一行,分多行時應用在行尾用 需要是最後乙個字元,最後一行不寫 c c 巨集命令的神奇用法。先看下面三條語句 cpp view plain copy define conn x,y x y define tochar x x define tostring x x 1 連線操作符 x y表...
define巨集定義
預處理指令 以 開頭的行,都預處理指令,用於指示編譯器做一些預處理工作。比如 include h 注 預處理指令不是語句,行尾不要加分號 define的兩種用法 1.定義乙個 數值 2.定義乙個 算式 注 工程中應該避免使用這兩種方式 定義乙個值 define pi 3.14 int main 定義...