MSVC不会正确扩展__VA_ARGS__

时间:2011-02-27 16:59:32

标签: visual-c++ c-preprocessor variadic-macros

考虑以下代码:

#define F(x, ...) X = x and VA_ARGS = __VA_ARGS__
#define G(...) F(__VA_ARGS__)
F(1, 2, 3)
G(1, 2, 3)

两个宏的预期输出为X = 1 and VA_ARGS = 2, 3,这就是我用GCC得到的,但是,MSVC将其扩展为:

X = 1 and VA_ARGS = 2, 3
X = 1, 2, 3 and VA_ARGS =

也就是说,__VA_ARGS__被扩展为一个参数,而不是分解为多个参数。

有什么方法吗?

3 个答案:

答案 0 :(得分:44)

MSVC的预处理器似乎与标准有很大不同 规范。
以下解决方法可能会有所帮助:

#define EXPAND( x ) x
#define F(x, ...) X = x and VA_ARGS = __VA_ARGS__
#define G(...) EXPAND( F(__VA_ARGS__) )

答案 1 :(得分:20)

我发布了the following Microsoft support issue

  

以下程序因预编译器而产生编译错误   错误地展开__VA_ARGS__

#include <stdio.h>

#define A2(a1, a2) ((a1)+(a2))

#define A_VA(...) A2(__VA_ARGS__)

int main(int argc, char *argv[])
{
    printf("%d\n", A_VA(1, 2));
    return 0;
}
     

预处理器将printf扩展为:       printf(“%d \ n”,((1,2)+()));

     而不是       printf(“%d \ n”,((1)+(2)));

我收到了Microsoft编译器团队开发人员的以下不满意答案:

  

嗨:在这种情况下,Visual C ++编译器的行为正常。如果组合规则,将与初始宏调用中的“...”匹配的标记组合在一起形成单个实体(16.3 / p12),其规则是在参数替换之前扩展子宏(16.3.1 / p1 )然后在这种情况下,编译器认为使用单个参数调用A2:因此出现错误消息。

答案 2 :(得分:1)

您使用的是什么版本的MSVC?您将需要Visual C ++ 2010。

__VA_ARGS__由C99首次引入。 MSVC从未尝试过支持C99,因此没有添加支持。

然而,现在,__VA_ARGS__包含在新的C ++标准C ++ 2011(以前称为C ++ 0x)中,微软显然计划支持它,因此它在最新版本的MSVC。

顺便说一下,您需要在源文件中使用.cpp后缀才能获得此支持。 MSVC很长一段时间没有更新其C前端。