参考自1
宏展开顺序大致可以归结为: 第一步:首先用实参代替形参,将实参代入宏文本中 第二步:如果实参也是宏,则展开实参 第三步:最后继续处理宏替换后的宏文本,如果仍包含宏,则继续展开 注意:如果在第二步,实参代入宏文本后,实参之前或之后遇到#或##,实参不再展开
#define cat(a,b) a ## b 宏调用:cat(cat(1, 2), 3)的展开顺序为: cat(cat(1, 2), 3) -->cat(1, 2) ## 3 -->cat(1, 2)3 首先代入实参cat(1, 2)以及3到宏文本a ## b中; cat(1,2)仍是宏,但后面是##,不再展开,结果为:cat(1, 2)3。
#define cat(a, b) a ## b #define xcat(x, y) cat(x, y)
宏调用xcat(xcat(1, 2), 3)的展开顺序为: xcat(xcat(1,2), 3) -->cat(xcat(1, 2), 3) -->cat(cat(1, 2), 3) -->cat(1 ## 2, 3) --> 1 ##2 ## 3 -->123 首先代入实参xcat(1, 2)以及3到宏文本cat(x, y); 发现实参xcat(1, 2)也是一个宏,则继续进行实参的宏展开; 发现实参cat(x, y)也是一个宏,则继续进行实参的宏展开; 在例2中,虽然也生成的cat(cat(1, 2), 3),这里是位于中间过程,例2中首先执行实参的宏展开cat(1, 2), 所以结果和例1不一样。
例2中以下顺序是错的: xcat(xcat(1,2), 3) --> cat(xcat(1, 2), 3) --> xcat(1, 2) ## 3 -->xcat(1, 2)3 展开后的宏文本中还包含宏,优先进行宏参数xcat(1, 2)的展开。
#define cat(a,b) a ## b #define xcat(x,y) cat(x,y) int main() { cat(cat(1,2),3); xcat(xcat(1,2),3); xcat(cat(1,2),3); return 0; }预编译展开后得到
int main() { cat(1,2)3; 123; 123; return 0; }对于大型C/C++工程,由于宏定义可能散落在各个头文件和Makefile当中。同时条件编译又是大型工程常用的技巧,所以宏定义的大量存在,给代码阅读增加了难度,如果搞不清楚宏定义的情况就无法掌握程序的执行流程。最简单的办法就是使用printf来打印这些宏,但是如果是带参数的宏就比较麻烦了。而且如果使用printf必须重新编译程序,并执行,当我们阅读的是内核源码或驱动程序,那重新执行的代价是相当可观的。如果在编译阶段可以打印宏的内容就可以省去这些麻烦。以下内容就阐述一种可行的方法。
首先介绍 #pragma message 。 它能够在编译信息输出窗口中输出相应的信息,这对于源代码信息的控制是非常重要的。其使用方法为: #pragma message(“消息文本”) 当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。 当我们在程序中定义了许多宏来控制源代码版本的时候,我们自己有可能都会忘记有没有正确的设置这些宏,此时我们可以用这条指令在编译的时候就进行检查。假设我们希望判断自己有没有在源代码的什么地方定义了_X86这个宏可以用下面的方法
#ifdef __cpluscplus #pragma message(“__cplusplus 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)
https://blog.csdn.net/buye1986/article/details/45100339 ↩︎
https://blog.csdn.net/xshbx/article/details/7981564 ↩︎