我很难理解在以下情况下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


我猜这里有某种“只能扩展一次同名宏”规则吗?我可以做些什么来使宏扩展我想要的方式吗?

最佳答案

C99草案说,在宏扩展中不允许递归:


6.10.3.4重新扫描并进一步替换


在替换列表中的所有参数被替换后,
#
##处理已经进行,所有地标预处理标记均已删除。产生的预处理令牌序列
然后重新扫描,以及所有后续预处理
源文件的令牌,用于替换更多的宏名称。
如果
在此扫描过程中找到了要替换的宏的名称
替换列表(不包括源文件的其余部分
预处理令牌),则不会替换它。此外,如果有的话
嵌套替换遇到要替换的宏的名称,它
不被替换。这些不可替换的宏名称预处理
令牌不再可用于进一步替换,即使它们
稍后在该宏名称的上下文中进行(重新)检查
否则将替换预处理令牌。



因此,X(A(A(x)))扩展为"A" _A(x),但正如您所见,该扩展本身并不是扩展的。

10-08 09:27
查看更多