Variadic 宏扩展出错了

Variadic macro expansion's going wrong

考虑以下代码

#define COMB(F, ...) F(__VA_ARGS__)


#define ADD(X, Y) (X + Y)


int foo() {
    return COMB(ADD, 1, 2);
}

我在 Godbolt 上做了一些实验。 Microsoft VS v19.22(带有 /E 标志)在预处理宏时失败。它给出了以下错误

int foo() {

    return (1, 2 + );

}

example.cpp

<source>(8): warning C4003: not enough arguments for function-like macro invocation 'ADD'

GCC(带有 -E 标志)简单地按预期输出

int foo() {
    return (1 + 2);
}

我看了一下C99标准。但我仍然不确定哪个编译器做得对?

我希望有人能帮我澄清一下。

我认为gcc是正确的。尽管 C11 6.10.3/12 将 COMB 的调用描述为具有两个参数(ADD1,2),但一旦 COMB 被扩展,生成的标记序列就是 ADD ( 1 , 2 ), 6.10.3.4/1 明确将第一次替换的结果重新扫描为预处理令牌序列。上一步中包含多个标记的参数不会以某种方式粘附到单个标记中以进行重新扫描。

6.10.3.4/1:

After all parameters in the replacement list have been substituted and # and ## processing has taken place, all placemarker preprocessing tokens are removed. The resulting preprocessing token sequence is then rescanned, along with all subsequent preprocessing tokens of the source file, for more macro names to replace

MSVC 在将 __VA_ARGS__ 传递给宏后对其进行扩展。您必须像这样手动展开宏:

#define EXPAND(x) x
#define COMB(F, ...) EXPAND(F(__VA_ARGS__))

#define ADD(X, Y) (X + Y)

在这种情况下,GCC 是正确的编译器。