C/C++宏替换实现详解
基本形式
#definenamereplacement_text
通常情况下,#define指令占一行,替换文本是define指令行尾部的所有剩余部分,但也可以把一个较长的宏定义分成若干行,这时需要在待续的行末尾加上一个反斜杠符``。
宏定义也可以带参数,这样可以对不同的宏调用使用不同的替换文本。例:
#definemax(A,B)((A)>(B)?(A):(B))
宏展开中的陷阱
仔细考虑一下max的展开式,其中的表达式会被计算两次,因此如果表达式中包含自增运算符或输入/输出等行为,则会出现不正确的情况,例如上述的宏max:
max(i++,j++)//wrong
另外还需要注意,适当使用圆括号以保证计算次序的正确性,例如:
#definesquare(x)x*x//wrong
当用square(z+1)调用该宏定义时会出错。
#undef
在头文件
可以通过#define取消名字的宏定义,这样做可以保证后续的调用是函数调用,而不是宏调用:
#undefgetchar intgetchar(void){...}
宏参数、#和##
如果在宏定义的替换文本中,参数名以#作为前缀则结果将被扩展为由实际参数替换该参数的带引号的字符串。例如,可以将它与字符串连接运算结合起来编写一个调试打印宏:
#definedprint(expr)printf(#expr"=%gn",expr)
使用语句
dprint(x/y);
调用该宏时,该宏将被扩展为:
printf("x/y""=%gn",x/y);
其中的字符串被拼接起来了,这样,该宏调用的效果等价于
printf("x/y=%gn",x/y);
预处理器运算符##为宏扩展提供了一种连接实际参数的手段。如果替换文本中的参数与##相邻,则该参数将被实际参数替代,##与前后的空白符将被删除,并对替换后的结果重新扫描。例如,下面定义的宏paste用于连接两个参数:
#definepaste(front,back)front##back
因此,宏调用paste(name,1)的结果将建立记号name1。
参考文献:
BrianW.Kernighan,DennisM.Ritchie.TheCProgrammingLanguage(SecondEdition)[M].机械工业出版社:北京,2004:76-77.
到此这篇关于C/C++宏替换实现详解的文章就介绍到这了,更多相关C/C++宏替换内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。