宏展开顺序分析

来源:互联网 发布:大数据分析 银行 编辑:程序博客网 时间:2024/05/16 02:40
The sequence of preprocessing tokens bounded by the outside-most matching parentheses
forms the list of arguments for the function-like macro. The individual arguments within the list are separated by comma preprocessing tokens. but comma preprocessing tokens between matching inner parentheses do not separate arguments.

6.8.3.1 Argument substitution
After the arguments for the invocation of a function-like niacro have been identified.argument substitution takes place. A parameter in the replacement list. unless preceded by a # or ## preprocessing token or followed by a ## preprocessing token (see below). is replaced by the corresponding argument after all macros contained therein have been expanded. Before being substituted, each argument’s preprocessing tokens are completely macro replaced as if they formed the rest of the translation unit: no other preprocessing tokens are available.

总结上述的内容,就是两点:

1。最外层括号中的逗号为实参分隔符,内层的不分隔该层实参;
2。带有预处理指令#或/和##的形参,不参与宏替换或宏展开


对于
#define cat(a,b) a ## b
cat(cat(1,2),3)

我们首先来分隔实参,这里有两个逗号,根据第一点,3左边的逗号是用来分隔最外层实参的,里面那个逗号在这一层的宏中不是实参分隔符,注意我说的是在这一层,这时候a = cat(1,2),b=3。接着继续进行宏展开或替换,由于a的后面和b的前面都有##指令,根据第二点,此时a和b都不再进行宏替换,因此a就是cat(1,2),b就是3,再进行粘贴,结果就是cat(1,2)3


对于
#define f(a) fff a
f(cat(cat(1,2),3))

cat(cat(1,2),3)整个就是a,由于a的前面后面都没有#和##,因此根据第二点继续进行宏替换,3左边的逗号是该层的实参分隔符,因此a=cat(1,2),b=3,继续根据第二点进行宏替换,a=1,b=2,于是就是(1##2)##3,结果就是fff 123


同样的道理可以用来分析
#define cat(a,b) a##b
#define xcat(a,b) cat(a,b)
xcat(xcat(1,2),3)

我用简化的步骤来一层一层替换下去:
xcat(xcat(1,2),3)
xcat(cat(1,2),3)
xcat(1##2, 3)
cat(1##2,3)
1##2##3
123


我在这里再补充一种情况,就是对于
#define N 10

如果想制造字符串化效果"10",应该怎么做?

直接#define X(N) #N是不行的,根据第一点,结果只会是"N",而不是"10",这时候应该这样定义宏:

#define N 10
#define Y(N) X(N)
#define X(N) #N

让Y(N)中的N先替换为10,就可以得到"10"了。

PS:宏展开从外层进行,将外层的参数展开,最后才是对外层展开