在將源代碼提交給編譯器之前,C語言預處理器將對源代碼做出一定修正。預處理器命令有很多如最常用的#include,#define命令. 預處理命令都是以#開頭,一般放在代碼的最左側(cè),通常定義的宏全部都是用大寫。 條件編譯
下面這一系列的指令都可以用來決定代碼的哪個部分應該被編譯,這些指令包括:#if,#elif,#else,#ifdef,#else,#ifdef以及#ifndef。以#if開頭的語句塊必須以#endif結(jié)尾。 可以使用條件編譯來注釋代碼,例如
以#if 表達式,如果表達式為假,那么這部分代碼就不會被編譯,為真才參與編譯。雖然你會說使用塊注釋也是可行的,但是可惜的是塊注視不支持嵌套,在某些環(huán)境下選擇#if 0確實是一個更好的選擇。測試代碼:
可以好似用#ifndef來避免頭文件被重復編譯:例如下面這段代碼:
同樣的技術(shù)可以用來定義一些常量,如:
宏定義
使用簡單的宏就不多說了,對于比較復雜的宏,常見的是使用類似于函數(shù)定義的宏,使用這種宏要特別注意宏的副作用。例如下面這段代碼: #define MULT(x, y) x * y
int z = MULT(3 + 2, 4 + 2);
一般情況,要對所有的實參添加括號,同時對宏體整體添加括號。 下面考察一種更加復雜的情況,交換兩個數(shù)的宏定義可以寫為:
對于第if語句會出現(xiàn)邏輯錯誤,因為這個if語句只執(zhí)行第一個異或操作。嗯,或許你已經(jīng)想到了,加上大括號,像下面這樣:
然而,還是對于第二個if語句還是不正確,因為預處理器替換之后就出現(xiàn)了‘};’語法錯誤。這里有一個技巧,正確的寫法如下:
這下就可以了,這里沒有給實參加括號的原因是因為我們只是針對變量的交換,不考慮那些表達式交換。 使用\分割宏體
如果宏體比較復雜的話,我們就需要使用\來分割宏體,示例代碼如下所示:
表達式合并
有時候在宏體中我們需要連接兩個參數(shù)的名字這時候可以使用##:
在struct中顯然每個名字都重復了一遍,通過使用##可以減少重復,方便維護:
符號字符串化
有時候我們經(jīng)常需要將傳入到宏中的符號或者叫做參數(shù)轉(zhuǎn)換為文本形式,這樣對于打印這些符號的時候比較方便,在寫一些調(diào)試模塊的時候,經(jīng)常會遇到這樣的需求,實現(xiàn)這個過程的語法很簡單,只需要在符號前面添加一個‘#’就可以了。例如下面這段代碼:
PRINT_TOKEN(foo);將被擴展 為printf("<foo>" " is %d" <foo>) 新版本的C語言支持將多個使用雙引號括起來的字符串練成一個整體的字符串。 下面為測試代碼:
|
|
來自: rookie > 《技術(shù)帖》