考虑以下代码:
#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__
被扩展为一个参数,而不是分解为多个参数。
有什么方法吗?
答案 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前端。