可变参数宏扩展出错

时间:2019-12-06 11:47:02

标签: c visual-studio gcc c99 variadic-macros

考虑以下代码

Function DoSomething(value As Integer) As Integer
    Dim foo As IFoo = New FirstFooImplementation()
    foo.DoProcess()
    Dim result1 As Integer = foo.EndResult
    foo = New SecondFooImplementation()
    foo.DoProcess()
    Dim result2 As Integer = foo.EndResult
    Return result1 + result2
End Function

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

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


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


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

GCC(带有-E标志)仅按预期输出

int foo() {

    return (1, 2 + );

}

example.cpp

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

我看了看C99标准。但是我仍然不确定哪个编译器在执行正确的操作?

我希望有人可以帮助我澄清这一点。

2 个答案:

答案 0 :(得分:2)

我认为gcc是正确的。尽管C11 6.10.3 / 12将COMB的调用描述为具有两个参数(ADD1,2),但是一旦COMB展开后,生成的令牌序列为ADD { {1}} ( 1 , 2和6.10.3.4/1很清楚,第一次替换的结果被重新扫描为预处理令牌序列。上一步中包含多个令牌的参数并没有以某种方式粘贴到单个令牌中以进行重新扫描。

6.10.3.4/1:

  

替换列表中的所有参数并替换#和##   处理已经完成,所有的地标预处理令牌均已删除。   然后重新扫描生成的预处理令牌序列,以及所有后续的   预处理源文件的令牌,以便替换更多的宏名称

答案 1 :(得分:1)

MSVC将__VA_ARGS__传递到宏后将其展开。您必须像这样手动扩展宏:

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

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

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