MSVC不会正确扩展__VA_ARGS__

uj2*_*uj2 48 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)
Run Code Online (Sandbox Code Playgroud)

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

X = 1 and VA_ARGS = 2, 3
X = 1, 2, 3 and VA_ARGS =
Run Code Online (Sandbox Code Playgroud)

也就是说,__VA_ARGS__将其扩展为单个参数,而不是分解为多个参数.

有什么方法吗?

Ise*_*ria 47

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

#define EXPAND( x ) x
#define F(x, ...) X = x and VA_ARGS = __VA_ARGS__
#define G(...) EXPAND( F(__VA_ARGS__) )
Run Code Online (Sandbox Code Playgroud)

  • 哦,我想我明白了……为了简单起见,让我们说`__VA_ARGS__` 是`1, 2`。`EXPAND(x) x` 使用 `F(__VA_ARGS__))` 并将其替换为字面上的 `F(1, 2)`,以便处理 `F(1, 2)` 而不是 `F(__VA_ARGS__)`,其中 `如果有意义的话,__VA_ARGS__` 被视为一个单一的实体...... (3认同)
  • 有人可以解释一下吗?“and VA_ARGS = __VA_ARGS__”是一段有效的 C 代码还是只是作为注释的人类可读文本?如果这是有效代码,“and VA_ARGS = __VA_ARGS__”在做什么?谢谢你。 (2认同)
  • @IseWisteria,@rbrich 在下面已经提到,现在有编译器开关 `/Zc:preprocessor` 请参阅[此处](https://learn.microsoft.com/en-us/cpp/preprocessor/preprocessor-experimental-overview ?view=msvc-160) 它将正确解压`__VA_ARGS__`。也许值得编辑您的答案,以将其包含在原始解决方案之外? (2认同)

小智 22

我发布了以下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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

  • 感谢您传递MS的基本原理。似乎他们将16.3.1 / p12中的“组合形成单个项目”解释为“组合形成单个,永久不可分割的预处理器令牌”,这似乎用处不大。我希望至少在16.3.4中给出的重新扫描步骤中,将替换的令牌重新分离,这似乎是其他编译器正在做的事情。 (3认同)
  • 现在有 [`/experimental:preprocessor`](https://docs.microsoft.com/en-us/cpp/build/reference/experimental-preprocessor?view=vs-2019) 或 `/Zc:preprocessor` 编译器使预处理器正确运行的开关。它为我解决了这个问题。 (3认同)
  • FWIW,这是同一问题的[另一个错误](https://connect.microsoft.com/VisualStudio/feedback/details/380090/variadic-macro-replacement),该团队承认这是一个错误,但说不是具有足够高的优先级进行修复(7年前)。 (2认同)