【发布时间】:2018-01-04 15:02:02
【问题描述】:
我很难理解 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 的副本 -
也许我的大脑工作不正常,但我不明白这是如何重复这些问题。在您链接的问题中,问题是先扩展宏然后再连接。我想做完全相反的事情:先连接然后展开。此外,至少正在发生一些扩展,或者我发布的示例根本不会扩展(例如,我们会得到 X(A(x)) - _A(x),但 _A(x) 显然会扩展)
-
我认为你的根本问题是宏预处理器在处理过程中相当简单,它作为一种一次性解析和输出。你想要做的实际上是一个不同的运算符
##运营商可以。听起来您希望运算符告诉预处理器使用##运算符生成一个符号,然后循环返回并重新评估该符号以查看是否需要对这个新符号执行任何其他操作。这就是预处理器的工作原理。 -
@MrMobster 如果
A和B本身是宏,并且您没有使用##来构建名称,那么您将无限期地递归。这是因为相应的扩展是在 参数替换 阶段完成的,这会在将所有宏参数放入替换列表之前完全扩展它们。作为。不受“蓝色油漆”的影响(又名,6.10.3.4p2,见托比的回答);这是不同的扫描。 重新扫描并进一步更换之后发生; 受 6.10.3.4 约束(因为这就是它正在做的事情),并且 不 支持同一宏的递归。
标签: c macros c-preprocessor