宏展开顺序
宏展开顺序大致可以归结为:
第一步:首先用实参代替形参,将实参代入宏文本中
第二步:第一步代入实参后,分两种情况:
1、实参之前遇到#或或之后遇到##,不管实参是不是宏,实参都将不再展开
2、如果实参前后没有#或##,那就继续展开实参,展开发现还是宏则继续展开,直到展开到不能展开为止
第三步:最后继续处理宏替换后的宏文本,如果仍包含宏,则继续展开
参考:https://blog.csdn.net/FJDJFKDJFKDJFKD/article/details/83385708
宏展开的几个注意事项:
1、每次宏展开的结果会被重复扫描,直到没有任何可展开的宏为止。
2、每展开一个宏,都会记住这次展开,在这个宏展开的结果及其后续展开中,不再对相同的宏做展开。宏不能自引用:https://gcc.gnu.org/onlinedocs/cpp/Self-Referential-Macros.html
3、带参数的宏,先对参数做展开,除非宏定义体中包含#或##
a) #表示将后续标识符转换为字符串
b) ##表示将两个标识符连接成一个标识符
c) 注意参数展开的结果中即使有逗号(,),也不视为参数的分隔符
如果宏定义中带有参数,而代码中出现同样标识符时没有参数,不视为宏。
参考:https://www.cnblogs.com/aquastone/p/c-macro-expansion.html
https://blog.csdn.net/KeLiaoo/article/details/109329661
编译阶段打印宏内容
首先介绍#pragma message 。 它能够在编译信息输出窗口中输出相应的信息,这对于源代码信息的控制是非常重要的。其使用方法为:
#pragma message(“消息文本”)
假设我们希望判断自己有没有在源代码的什么地方定义了_X86这个宏可以用下面的方法
#ifdef _X86
#pragma message(“_X86 macro activated!”)
#endif
下面的示例演示如何在编译阶段打印宏内容。
//两个用于测试的宏
#define PI 3.1415926
#define MAX(a,b) (a)>(b) ? (a) :(b)
//首先定义两个辅助宏
#define PRINT_MACRO_HELPER(x) #x
#define PRINT_MACRO(x) #x": "PRINT_MACRO_HELPER(x)
//编译阶段打印宏内容
#pragma message(PRINT_MACRO(PI))
#pragma message(PRINT_MACRO(PI2))
#pragma message(PRINT_MACRO(MAX(a,b)))
#pragma message(PRINT_MACRO(MAX(x,y)))
结果输出
note: #pragma message: PI=3.1415926
//PRINT_MACRO中的两个x都被替换为PI,PRINT_MACRO_HELPER中的#x替换为宏PI的内容
note: #pragma message: PI2=PI2
//PI2不存在的情况下PRINT_MACRO_HELPER将#x换做PI2
note: #pragma message: MAX(a,b)=(a)>(b) ? (a) :(b)
note: #pragma message: MAX(x,y)=(x)>(y) ? (x) :(y)