是通过令牌连接未指定的行为重复宏调用吗?

Kyl*_*yle 5 c macros c-preprocessor c11

C11标准承认关于宏扩展中可能出现的至少一种情况的模糊性,当像宏这样的函数扩展到其未被识别的名称时,并且由下一个预处理令牌调用.标准中给出的例子是这样的.

#define f(a) a*g
#define g(a) f(a)

// may produce either 2*f(9) or 2*9*g
f(2)(9)
Run Code Online (Sandbox Code Playgroud)

该示例没有说明当扩展宏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)
Run Code Online (Sandbox Code Playgroud)

test(X)扩展到test_help_A( arity(X) ),这将调用test_help_A上重新扫描,其中取代前扩大其精氨酸,等是相同的test_help_A(1),其产生test_help_B(1),其产生test_help_1.这很清楚.

所以,问题就在这里.test_help_1是使用一个字符产生的,1来自扩展的arity.那么test_help_1再次召唤arity 的扩张呢?我的gcc和clang版本都是这么认为的.

任何人都可以争辩说gcc和clang所做的解释是标准中的某些要求吗?

是否有人意识到以不同方式解释这种情况的实现?

Jen*_*edt 3

我认为 gcc 和 clang 的解释是正确的。的两个扩展arity不在同一调用路径中。test_help_A第一个来自于论证的扩展,第二个来自于test_help_A自身的扩展。

这些规则的想法是保证不能有无限递归,这里保证了这一点。两次调用之间的宏评估取得了进展。