MSVC 未正确扩展 __VA_ARGS__

发布于 2024-10-19 14:21:16 字数 373 浏览 2 评论 0原文

考虑这段代码:

#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 和 VA_ARGS = 2, 3,这就是我使用 GCC 得到的结果,但是,MSVC 将其扩展为

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

: >__VA_ARGS__ 扩展为单个参数,而不是分解为多个参数。

有什么办法解决这个问题吗?

Consider this code:

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

The expected output is X = 1 and VA_ARGS = 2, 3 for both macros, and that's what I'm getting with GCC, however, MSVC expands this as:

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

That is, __VA_ARGS__ is expanded as a single argument, instead of being broken down to multiple ones.

Any way around this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

愁以何悠 2024-10-26 14:21:17

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

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

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

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

What version of MSVC are you using? You will need Visual C++ 2010.

__VA_ARGS__ was first introduced by C99. MSVC never attempted to support C99, so the support was not added.

Now, however, __VA_ARGS__ is included in the new C++ standard, C++2011 (previously known as C++0x), which Microsoft apparently plans to support, so it has been supported in recent versions of MSVC.

BTW, you will need to use a .cpp suffix to your source file to get this support. MSVC hasn't updated its C frontend for a long time.

一个人的旅程 2024-10-26 14:21:16

编辑:
此问题可以通过使用来解决
最近的 MSVC 中的 /Zc:preprocessor/experimental:preprocessor 选项。
详情请参阅
此处

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

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

Edit:
This issue might be resolved by using
/Zc:preprocessor or /experimental:preprocessor option in recent MSVC.
For the details, please see
here.

MSVC's preprocessor seems to behave quite differently from the standard
specification.
Probably the following workaround will help:

#define EXPAND( x ) x
#define F(x, ...) X = x and VA_ARGS = __VA_ARGS__
#define G(...) EXPAND( F(__VA_ARGS__) )
神经大条 2024-10-26 14:21:16

我发布了 以下 Microsoft 支持问题

由于预编译器的原因,以下程序会出现编译错误
错误地扩展了 __VA_ARGS__

#include ;

#定义 A2(a1, a2) ((a1)+(a2))

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

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

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

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

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

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

I posted the following Microsoft support issue:

The following program gives compilation error because the precompiler
expands __VA_ARGS__ incorrectly:

#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;
}

The preprocessor expands the printf to:
printf("%d\n", ((1, 2)+()));

instead of
printf("%d\n", ((1)+(2)));

I received the following unsatisfying answer from a Microsoft compiler team developer:

Hi: The Visual C++ compiler is behaving correctly in this case. If you combine the rule that tokens that match the '...' at the inital macro invocation are combined to form a single entity (16.3/p12) with the rule that sub-macros are expanded before argument replacement (16.3.1/p1) then in this case the compiler believes that A2 is invoked with a single argument: hence the error message.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文