可变参数宏是非标准的吗?

34

在debug版本中,我通常使用Clang编译器,因为它能更好地格式化警告和错误,并且使其更容易跟踪和修复。

但最近,当我添加了一个带有可变参数的宏时,Clang 给我返回了以下信息(来自一个虚拟项目):

main.cpp:5:20: warning: named variadic macros are a GNU extension [-Wvariadic-macros]
#define stuff3(args...)  stuff_i(args)
我知道在很多编译器中,包括Visualstudio、Sunstudio和GCC, macroname(args...) 是可以编译通过的。但为了确保clang也能正常运行,我尝试了另外两种可变参数扩展的方式:

方法一:

#define stuff1(...)  stuff_i(...)

第二点:

#define stuff2(...)  stuff_i(__VA_ARGS__)

在两者上我都收到这个消息:

main.cpp:3:16: warning: variadic macros were introduced in C99 [-Wvariadic-macros]

这让我想知道变参宏实际上是否是C++标准的一部分(当然,我知道预处理器是独立解释的)?


1
C99和C++0x正式支持版本2。C++03不支持任何可变参数宏。版本1是GCC特定的扩展。 - sellibitze
当您使用GCC编译时,有一个-pedantic选项,它应该报告所使用的扩展功能,例如变长数组或可变参数宏。在GCC中,它们被包含在内,因为它们是C99的一部分,逻辑已经实现,所以让C++开发者受益似乎是个好主意 :) - Matthieu M.
@Matthieu M:确实,我也认为这个特性应该是 C++ 的一部分,因为它已经是 C99 的一部分了......有趣的是,gcc 没有说命名可变参数宏确实是 GNU 扩展,而只是说它们不是标准的一部分:“warning: ISO C does not permit named variadic macros”。 - user350814
4个回答

42

引用自 维基百科:

可变参数宏是在C语言标准的ISO/IEC 9899:1999(C99)修订版中于1999年引入的,在C++语言标准的ISO/IEC 14882:2011(C++11)修订版中于2011年引入的。

因此,从C99和C++11开始,它是标准规范,但在C++03中是GNU扩展。


30

从C++11开始,可变参数宏现在已经包含在标准C++中。C++11标准的第16.3节具体规定了可变参数宏,使其与C99中的可变参数宏兼容(问题中的第二种形式)。

以下是C++中符合标准的可变参数宏定义示例:

#define foo(x, y, ...)    bar(x, y, __VA_ARGS__)

2
它符合标准,但如果维基百科是正确的话,它也会受到逗号错误的影响。 - Alexei Averchenko
@AlexeiAverchenko:我在gcc文档中看到,如果在...中没有放置任何内容,逗号将被删除。然而今天我将一些代码移植到clang上,却遇到了“预期表达式”错误,我还没有完全理解它。可能有关联。 - v.oddou
__VA_OPT__ 在 C++20 中被引入以解决这个问题。 - L. F.

4
在您提供的示例“Number 2”中,它们是C99标准,并且通常C++编译器的预处理器与C和C++编译相同。即使在微软VC ++上,它们也得到了支持,尽管其对C99的兼容性一直很顽固。因此,在GCC和Microsoft VC++之间,几乎没有理由不使用它们。即使在我使用的大多数嵌入式系统编译器中,它们也得到了支持。
但是,请避免使用“Number 1”的形式,它是GCC特定的,毫无疑问已经被弃用。

0

标准在 16.3 宏替换 中指出:

标识符 _ _ VA_ARGS _ _ 只能出现在使用省略号符号作为参数的函数宏的替换列表中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接