平台开发过程中,经常出现多层编译规则嵌套问题,即采用多层级Makefile编译规则。部分模块参数在外围模块配置,这时就可通过gcc -DTESTMACRO传入代码中。
此时,根据宏TESTMACRO值的类型,分两种情况:
1)整型值,没什么问题,可直接使用;
2)字符串,则可能出现如下情况:第一层Makefile中写的是“dev.test.com.cn”,传到第二层Makefile就变成了dev.test.com.cn,也就是说在源码中,TESTMACRO已经不是"dev.test.com.cn",而是dev.test.com.cn,这就意味着TESTMACRO不能直接被当成字符串来使用。
情形2),若还想将TESTMACRO当成字符串处理,就可以使用gcc工具提供的字符串化功能。
实例:
1)
先定义两个宏:
#define MACRO_STR(x) #x
#define XMACRO_STR(s) MACRO_STR(s)
然后:
#define MACRO_INT 123456
则 XMACRO_STR(MACRO_INT),等价于 #define XMACRO_STR "123456",注意这里不能直接用MACRO_STR(MACRO_INT),因为MACRO_STR(MACRO_INT)等价于"MACRO_INT"。
解释:
Macro arguments are completely macro-expanded before they are substituted into a macro body, unless they are stringified or pasted with other tokens. After substitution, the en-tire macrobody, including the substituted arguments, is scanned again for macros to be expanded.
即GCC在宏预处理阶段,有一条排外规则,那就是若宏参数被用于字符串化或者与其它标签连接,则不会被替代!
2)
定义宏:
#define DIR_NAME "/etc/config/"
则fopen(DIR_NAME ##ddns, 'r')等价于fopen("/etc/config/ddns", 'r')
总之,在GCC中:
"#”是将宏字符串化(Stringification),“##”是将##左右两边的标签组合在一起(token pasting or token concatenation)