程序預處理 -- 宏定義

大部分入門教材都很少提到預處理,在此給大家分享一下預處理各指示字的應用。

我們知道,源代碼要編譯成可執行文件,首先就必須經過預處理。而預處理就是把源文件中的指示字進行處理。而指示字(directive)一般放在程序開頭,並以#爲開頭的代碼。當然,指示字也可以出現在程序的任何地方。

來看看指示字之一的#define  :宏定義

所謂宏定義,說白了就是把一個表達式或常量定義成一個符號,這個符號可以帶有參數。程序在預處理的時候就把這個符號用等價的代碼替換。當然

舉個例子:

第13行定義100爲A,類似於const的使用,不過兩者有本質的區別。

第14行定義showint(a)爲一個printf的函數,並帶有參數a。

可以看看預處理後的結果:

頭文件被展開,宏定義也被展開。

同時也可以看到,宏定義在預處理時就被處理掉了。而const要等到彙編之後才能處理,也就是說,處理的優先級是先處理宏定義。

下面在看看:

(\反斜槓可用來分割代碼,方便閱讀)

輸出結果是:

並沒有輸出ocean;

這說明宏定義在字符串中是不被處理的。當然,如果把上面例子用“”號隔開ARGTERM,就可以傳遞參數,打印出ocean了。當然,也可以在 參數前 加#號把宏定義字符串化(即把參數換成#ARGTERM)。

另外,用宏定義來定義函數時,既要注意效率的問題,也要注意優先級的問題,後者可能會帶來重大錯誤;

例如:

#define max(A,B) (A>B?A:B)
//這樣寫對嗎?
//錯誤1:沒有考慮到優先級;假如有如下一段代碼:
max((a+b),(c+d));//預處理後會怎麼樣呢?
不難得知:結果爲
a+b>c+d?a+b:c+d;
結合優先級的問題,結果不難知道

再者,並且,參數將會運算兩次,這代表着什麼?

1、運算效率的不成熟,憑空多了1次運算;

2、如果上面的參數是a++,b++呢?那就更加糟糕了;

儘管如此,宏定義還是非常有價值的。例如,<ctype.h>頭文件中定義的函數也是常常通過宏實現的;(引用K&R的《C程序設計》)


宏(macro)既可以是靜態的,也可以是動態可變的。即宏的參數可以是可變個。下面纔是重磅

宏定義如#define P(...) printf(__VA_ARGS__)可以輸入多個參數;

這裏要注意__VA_ARGS__兩邊是用雙下劃線。

預處理後的結果是:

處理成功;

 

綜上:

宏定義是可帶參數的,可以是固定個,也可以是可變個。可變個時用 ... 來代替,並儲存在__VA_ARGS__之中

宏定義:可以是個常量

            也可以是個帶參數的表達式

            也可以是個帶可變參數的表達式

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章