C/C++宏替換詳解

1. 基本形式

#define name replacement_text

一般狀況下,#define 指令佔一行,替換文本是 define 指令行尾部的全部剩餘部分,但也能夠把一個較長的宏定義分紅若干行,這時須要在待續的行末尾加上一個反斜槓符 ``。函數

宏定義也能夠帶參數,這樣能夠對不一樣的宏調用使用不一樣的替換文本。例:調試

#define max(A, B) ((A) > (B) ? (A) : (B))

2. 宏展開中的陷阱

仔細考慮一下 max 的展開式,其中的表達式會被計算兩次,所以若是表達式中包含自增運算符或輸入/輸出等行爲,則會出現不正確的狀況,例如上述的宏 maxcode

max(i++, j++)  // wrong

另外還須要注意,適當使用圓括號以保證計算次序的正確性,例如:字符串

#define	square(x)	x * x	// wrong

當用 square(z+1) 調用該宏定義時會出錯。get

3. #undef

在頭文件 <stdio.h> 中,getcharputchar 函數在實際中經常被定義爲宏,這樣能夠避免處理字符時調用函數所需的運行時開銷。<ctype.h> 頭文件中定義的函數也經常是經過宏實現的。it

能夠經過 #define 取消名字的宏定義,這樣作能夠保證後續的調用是函數調用,而不是宏調用:io

#undef getchar

int getchar(void) { ... }

4. 宏參數、###

若是在宏定義的替換文本中,參數名以 # 做爲前綴則結果將被擴展爲由實際參數替換該參數的帶引號的字符串。例如,能夠將它與字符串鏈接運算結合起來編寫一個調試打印宏:ast

#define	dprint(expr)	printf(#expr " = %gn", expr)

使用語句class

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


參考文獻:

  1. Brian W. Kernighan, Dennis M. Ritchie.The C Programming Language (Second Edition)[M].機械工業出版社:北京,2004:76-77.
相關文章
相關標籤/搜索