它在C++性病16.3.4中说:
宏调用替换产生的预处理令牌序列与源文件的所有后续预处理令牌一起重新包装,以获得更多要替换的宏名称。 如果在此替换列表扫描过程中找到要替换的宏的名称(不包括源文件的其他预处理令牌),则不会替换它。 此外,如果任何嵌套的替换遇到要替换的宏的名称,则不会替换它。 这些未被替换的宏名称预处理令牌不再可供进一步替换,即使它们稍后(重新)在否则会被替换的宏名称预处理令牌的上下文中进行检查。
嵌套宏替换究竟是什么?
具体考虑:
#define f(x) 1 x
#define g(x) 2 x
g(f)(g)(3)我本以为会有以下情况:
g(f)(g)(3) <-- first replacement of g, ok
2 f(g)(3) <-- nested replacement of f, ok
2 1 g(3) <-- second nested replacement of g, don't replace, stop然而gcc却出人意料地进行了g的第二次替换,生产:
2 1 2 3有什么想法吗?
更新:
经过大量的研究,让我用一个简单的例子来澄清这个问题:
#define A(x) B
#define B(x) A(x)
A(i)(j)这一范围扩大如下:
A(i)(j)
B(j)
A(j)该标准没有指定是否应该将A(j)扩展为B。委员会决定以这种方式放弃它,因为现实世界的程序不需要依赖于这种行为,所以不管是不扩展A(j)还是将A(j)扩展到B都被认为是一致的。
发布于 2013-03-28 00:45:11
这就解释了最初的意图,以及为什么标准中没有对这一问题作出任何澄清:
active.html#268
G0(42)的扩展顺序如下:
G0(42) 0(G_1)(42) G_1(42) 0(42)
问题是,在这个序列的最后一行中使用NIL是否符合引用文本中不可替换的条件。如果是的话,结果将是NIL(42)。如果没有,结果将是简单的42。
本文中的42**,委员会的最初意图是,其作者戴夫·普罗瑟提供的替换算法的原始伪代码描述证明了这一结果应该是 J11。然而,英文描述忽略了伪代码的一些微妙之处,因此可以说给出了一个错误的答案。
建议的分辨率(迈克·米勒):剪短
2004年4月WG14会议记录(通过Tom ):
早在20世纪80年代,一些WG14人士就认识到,“非替代”语句与试图生成伪代码的尝试之间存在着微小的差异。委员会的决定是,“在野外”不会有任何现实的项目进入这一领域,试图减少不确定性不值得冒改变实现或程序的一致性状态的风险。发布于 2013-03-23 07:43:32
g(x)总是被2 x取代。在g的第二个嵌套替换中,使用x=3调用x=3,从而生成结果2 3。我的理解是,编译器不会用它的值替换宏,以防产生无限循环:
#define g( x ) f( x )
#define f( x ) g( x )
g( 1 ) -- > f( 1 ) --> stop 发布于 2013-05-22 08:26:26
因为它提到了“(不包括源文件的其他预处理令牌)。g的第一个替代者只看到f。现在,f有资格用从文件的其余部分获取的预处理令牌来替换,但是程序没有记录f是由g生成的。f(g)的替换会产生一个同样不受递归污染的g。
嵌套替换是由另一个替换包含的替换,而不是其令牌来自另一个替换的替换。根据后一种定义,替代者可能有几个相互排斥的嵌套父母。
https://stackoverflow.com/questions/15583021
复制相似问题