#define name replacement_text 複製**
通常情況下,#define
指令佔一行,替換文字是define
指令行尾部的所有剩餘部分,但也可以把乙個較長的巨集定義分成若干行,這時需要在待續的行末尾加上乙個反斜槓符 ``。
巨集定義也可以帶引數,這樣可以對不同的巨集呼叫使用不同的替換文字。例:
#define max(a, b) ((a) > (b) ? (a) : (b)) 複製**
仔細考慮一下max
的展開式,其中的表示式會被計算兩次,因此如果表示式中包含自增運算子或輸入/輸出等行為,則會出現不正確的情況,例如上述的巨集max
:
max(i , j ) // wrong 複製**
另外還需要注意,適當使用圓括號以保證計算次序的正確性,例如:
#define square(x) x * x // wrong 複製**
當用square(z 1)
呼叫該巨集定義時會出錯。
在標頭檔案中,
getchar
與putchar
函式在實際中常常被定義為巨集,這樣可以避免處理字元時呼叫函式所需的執行時開銷。標頭檔案中定義的函式也常常是通過巨集實現的。
可以通過#define
取消名字的巨集定義,這樣做可以保證後續的呼叫是函式呼叫,而不是巨集呼叫:
#undef getchar int getchar(void) 複製**
如果在巨集定義的替換文字中,引數名以#
作為字首則結果將被擴充套件為由實際引數替換該引數的帶引號的字串。例如,可以將它與字串連線運算結合起來編寫乙個除錯列印巨集:
#define dprint(expr) printf(#expr " = %gn", expr) 複製**
使用語句
dprint(x/y); 複製**
呼叫該巨集時,該巨集將被擴充套件為:
printf("x/y" " = %gn", x/y); 複製**
其中的字串被拼接起來了,這樣,該巨集呼叫的效果等價於
printf("x/y = %gn", x/y); 複製**
預處理器運算子##
為巨集擴充套件提供了一種連線實際引數的手段。如果替換文字中的引數與##
相鄰,則該引數將被實際引數替代,##
與前後的空白符將被刪除,並對替換後的結果重新掃瞄。例如,下面定義的巨集paste
用於連線兩個引數:
#define paste(front, back) front ## back 複製**
因此,巨集呼叫paste(name, 1)
的結果將建立記號name1
。 C C 巨集詳解
c c 巨集詳解 眾多c 書籍都忠告我們c語言巨集是萬惡之首,但事情總不如我們想象的那麼壞 眾多c 書籍都忠告我們c語言巨集是萬惡之首,但事情總不如我們想象的那麼壞,就如同goto一樣。巨集有 乙個很大的作用,就是自動為我們產生 如果說模板可以為我們產生各種型別的 型別替換 那麼巨集其實可以為我們在...
C C 巨集詳解
眾多c 書籍都忠告我們c語言巨集是萬惡之首,但事情總不如我們想象的那麼壞,就如同goto一樣。巨集有 乙個很大的作用,就是自動為我們產生 如果說模板可以為我們產生各種型別的 型別替換 那麼巨集其實可以為我們在符號上產生新的 即符號替換 增加 關於巨集的一些語法問題,可以在google上找到。相信我,...
C,C 巨集中 與 詳解
文中 file 與示例1可以參見 使用 ansi c and microsoft c 中常用的預定義巨集 巨集中的 的功能是將其後面的巨集引數進行字串化操作 stringizing operator 簡單說就是在它引用的巨集變數的左右各加上乙個雙引號。如定義好 define string x x之後...