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.
相关文章
相关标签/搜索