62

考虑这段代码:

#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__将其扩展为单个参数,而不是分解为多个参数。

有什么办法吗?

4

3 回答 3

60

编辑:这个问题可以通过 在最近的 MSVC 中使用/Zc:preprocessoror选项来解决。/experimental:preprocessor详情请看 这里

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

#define EXPAND( x ) x
#define F(x, ...) X = x and VA_ARGS = __VA_ARGS__
#define G(...) EXPAND( F(__VA_ARGS__) )
于 2011-02-27T17:24:54.253 回答
28

我发布了以下 Microsoft 支持问题

以下程序给出编译错误,因为预编译器扩展__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 是使用单个参数调用的:因此出现错误消息。

于 2011-09-18T06:11:50.843 回答
0

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

__VA_ARGS__ 最早由 C99 引入。MSVC 从未尝试支持 C99,因此未添加支持。

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

顺便说一句,您需要对.cpp源文件使用后缀才能获得此支持。MSVC 很久没有更新它的 C 前端了。

于 2011-09-18T06:28:13.243 回答