C语言宏嵌套 【引用】C语言宏的嵌套问题 http://zhangzhibiao02005.blog.163.com/blog/static/37367820201182585935895/ (修改原文第二个程序中一处错误,return 1;改为return 0;CodeBlock下运行验证,并附上不包含stdio头文件的预处理后文件) 在C语言的宏中是容许嵌套的,其嵌套后,一般的展开规律像函数的参数一样,先展开参数,再分析函数,所以展开顺序是由内而外,但是当宏中有#则不再展开参数了,如果宏中有##,则先展开函数,再展开里面的参数。 如下面的例子:
它的输出结果为:
对于宏TO_STRING,它的定义中没有#,所以先展开里面的“PARAM( ADDPARAM( 1 ) )”,由于PARAM中有#,所以里面展开的结果为ADDPARAM( 1 ),然后外面再展开,其结果为"ADDPARAM( 1 )" 而对于TO_STRING2,其定义中有#,所以直接展开,其结果为PARAM( ADDPARAM( 1 ) ) 去掉include的预处理后文件为:
注:\"为转义字符反斜杠表示的双引号。 而对于下面的例子:
其输出结果为:
因为首先分析TO_STRING的参数TO_STRING2(PARAM( ADDPARAM( 1 ) ) ),而对于TO_STRING2(x),由于其定义中有##,所以先展开该函数,其结果为a_PARAM(ADDPARAM( 1 )),而ADDPARAM( 1 )展开,结果为INT_1,所以其总结果为a_PARAM( INT_1 )
【引用结束】 【总结】 先展开宏,再展开宏参数,这种说法不太妥当,我总结的宏处理过程如下: 遇到宏名后(1)
详细地解释一下整个过程并做验证 【经典题过程】 #define f(a,b) a##b #define g(a) #a #define h(a) g(a) h(f(1,2)) (2) (1)(3)(5) h(12) (4) g(12) (1)(3)(5) "12" g(f(1,2)) (3) "f(1,2)" // 受字符串符号屏蔽 【对于那个讨论帖的问题】 #define cat(a,b) a ## b #define f(a) fff a #define ab AB cat(cat(1,2),3) cat(1,2)3 cat(a,b) ab AB f(cat(cat(1,2),3)) fff cat(cat(1,2),3) fff cat(1,2)3 【例子1过程】 遇到宏名后(1) 检查对应的宏体中是否含有#和##运算符 无——处理宏参数(实参)(2) 遇到宏名,回到(1) 没有遇到,在宏体中用实参字符串替换形式参数,再检查是否遇到宏名(4) ... 有——不检查宏参数,在宏体中用实参字符串替换形式参数,再检查是否含有宏名(3) 遇到宏名,回到(1) 没有遇到,结束(5) #define TO_STRING2( x ) #x #define TO_STRING( x ) TO_STRING1( x ) #define TO_STRING1( x ) #x #define PARAM( x ) #x #define ADDPARAM( x ) INT_##x TO_STRING(PARAM( ADDPARAM( 1 ) ) ) TO_STRING("ADDPARAM( 1 )" ) TO_STRING1("ADDPARAM( 1 )" ) "\"ADDPARAM( 1 )\"" TO_STRING2(PARAM( ADDPARAM( 1 ) ) ) "PARAM( ADDPARAM( 1 ) )" 【例子2过程】 #define TO_STRING2( x ) a_##x #define TO_STRING( x ) TO_STRING1( x ) #define TO_STRING1( x ) #x #define PARAM( x ) #x #define ADDPARAM( x ) INT_##x TO_STRING(TO_STRING2(PARAM( ADDPARAM( 1 ) ) )) TO_STRING(a_PARAM( ADDPARAM( 1 ) )) TO_STRING(a_PARAM( INT_1 )) TO_STRING1(a_PARAM( INT_1 )) "a_PARAM( INT_1 )" |
|