共计 1049 个字符,预计需要花费 3 分钟才能阅读完成。
根本模式
#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)
调用该宏定义时会出错。
#undef
在头文件 <stdio.h>
中,getchar
与 putchar
函数在理论中经常被定义为宏,这样能够防止解决字符时调用函数所需的运行时开销。<ctype.h>
头文件中定义的函数也经常是通过宏实现的。
能够通过 #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
。
参考文献:
- Brian W. Kernighan, Dennis M. Ritchie.The C Programming Language (Second Edition)[M]. 机械工业出版社: 北京,2004:76-77.