C11标准承认关于宏扩展中可能出现的至少一种情况的模糊性,当像宏这样的函数扩展到其未被激活的名称时,并且由下一个预处理令牌调用。标准中给出的例子是这样的。
#define f(a) a*g
#define g(a) f(a)
// may produce either 2*f(9) or 2*9*g
f(2)(9)
该示例没有说明当扩展宏M时会发生什么,并且结果的全部或部分通过令牌连接贡献给第二个预处理令牌M,后者被调用。
问题:此类调用是否被阻止?
以下是此类调用的示例。这个问题往往只在使用一组相当复杂的宏时出现,所以这个例子是为了简单起见而设计的。
// arity gives the arity of its args as a decimal integer (good up to 4 args)
#define arity(...) arity_help(__VA_ARGS__,4,3,2,1,)
#define arity_help(_1,_2,_3,_4,_5,...) _5
// define 'test' to mimic 'arity' by calling it twice
#define test(...) test_help_A( arity(__VA_ARGS__) )
#define test_help_A(k) test_help_B(k)
#define test_help_B(k) test_help_##k
#define test_help_1 arity(1)
#define test_help_2 arity(1,2)
#define test_help_3 arity(1,2,3)
#define test_help_4 arity(1,2,3,4)
// does this expand to '1' or 'arity(1)'?
test(X)
test(X)
扩展为test_help_A( arity(X) )
,在重新扫描时调用test_help_A
,在替换前扩展其arg,因此与test_help_A(1)
相同,后者生成test_help_B(1)
},产生test_help_1
。这很清楚。
所以,问题就在这里。 test_help_1
是使用来自1
扩展的字符arity
生成的。那么test_help_1
的扩张能否再次召唤arity?我的gcc和clang版本都是这么认为的。
答案 0 :(得分:2)
我认为gcc和clang的解释是正确的。 arity
的两个扩展不在同一个调用路径中。第一个来自test_help_A
论证的扩展,第二个来自test_help_A
本身的扩张。
这些规则的思想是保证在这里无法保证无限递归。两次调用之间的宏评估取得了进展。