我很难理解在以下情况下C预处理器如何应用重写规则。我有以下宏:
#define _A(x) "A" _##x
#define _B(x) "B" _##x
#define X(x) _##x
这个想法是每个宏使用连接来创建一个新表达式,这个表达式本身可以是一个宏——如果它是一个宏,我希望它会被展开:
现在,以下内容展开的方式正如我所期望的那样:
X(x) expands to _x
X(A(x)) expands to "A" _x
X(A(B(x))) expands to "A" "B" _x
然而,一旦相同的宏被多次使用,扩展将停止:
X(A(A(x))) expands to "A" _A(x), expected "A" "A" _x
X(B(B(x))) expands to "B" _B(x), expected "B" "B" _x
X(A(B(A(x)))) expands to "A" "B" _A(x), expected "A" "B" "A" _x
X(A(B(A(B(x))))) expands to "A" "B" _A(B(x)), expected "A" "B" "A" "B" _x
我猜这里有某种“同名宏只能扩展一次”的规则在起作用?是否有什么办法让宏按照我想要的方式扩展?
##
运算符,它不会评估宏;这是Nested macro expansion的重复。 - underscore_d##
运算符的操作符。听起来你想要一个操作符告诉预处理器使用##
运算符生成一个符号,然后循环回去重新评估该符号,看是否有其他需要对这个新符号进行的操作。但这不是预处理器的工作方式。 - Richard ChambersA
和B
本身就是宏,而且你没有使用##
来构建名称,则会无限递归。这是因为相关的扩展是在参数替换阶段完成的,在将它们放入替换列表之前完全展开所有宏参数。a.s.不受“蓝色涂料”(又名6.10.3.4p2,请参见Toby的答案)的影响;它是一种不同的扫描方式。重新扫描和进一步替换发生在此之后;受到6.10.3.4的影响(因为这就是它所做的),不支持相同宏的递归。 - H Walters