目錄
- 1. 基本形式
- 2. 宏展開中的陷阱
- 3. #undef
- 4. 宏引數、# 和 ##
1. 基本形式
#define name replacement_text
通常情況下,#define 指令占一行,替換文本是 define 指令行尾部的所有剩余部分,但也可以把一個較長的宏定義分成若干行,這時需要在待續的行末尾加上一個反斜杠符 ``,
宏定義也可以帶引數,這樣可以對不同的宏呼叫使用不同的替換文本,例:
#define max(A, B) ((A) > (B) ? (A) : (B))
2. 宏展開中的陷阱
仔細考慮一下 max 的展開式,其中的運算式會被計算兩次,因此如果運算式中包含自增運算子或輸入/輸出等行為,則會出現不正確的情況,例如上述的宏 max:
max(i++, j++) // wrong
另外還需要注意,適當使用圓括號以保證計算次序的正確性,例如:
#define square(x) x * x // wrong
當用 square(z+1) 呼叫該宏定義時會出錯,
3. #undef
在頭檔案 <stdio.h> 中,getchar 與 putchar 函式在實際中常常被定義為宏,這樣可以避免處理字符時呼叫函式所需的運行時開銷,<ctype.h> 頭檔案中定義的函式也常常是通過宏實作的,
可以通過 #define 取消名字的宏定義,這樣做可以保證后續的呼叫是函式呼叫,而不是宏呼叫:
#undef getchar
int getchar(void) { ... }
4. 宏引數、# 和 ##
如果在宏定義的替換文本中,引數名以 # 作為前綴則結果將被擴展為由實際引數替換該引數的帶引號的字串,例如,可以將它與字串連接運算結合起來撰寫一個除錯列印宏:
#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,
參考文獻:
- Brian W. Kernighan, Dennis M. Ritchie.The C Programming Language (Second Edition)[M].機械工業出版社:北京,2004:76-77.
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/224504.html
標籤:C
上一篇:哪里可以免費聽到周杰倫的歌曲?請看這里,教你免費聽歌
下一篇:C/C++宏替換詳解
