【发布时间】:2011-08-01 02:59:28
【问题描述】:
在 C99 中有一个 well-known problem 带有空参数,用于可变参数宏。
示例:
#define FOO(...) printf(__VA_ARGS__)
#define BAR(fmt, ...) printf(fmt, __VA_ARGS__)
FOO("this works fine");
BAR("this breaks!");
根据C99标准,上面BAR()的使用确实是不正确的,因为它会扩展为:
printf("this breaks!",);
注意结尾的逗号 - 不可行。
一些编译器(例如:Visual Studio 2010)会悄悄地为您删除尾随逗号。其他编译器(例如:GCC)支持将## 放在__VA_ARGS__ 前面,如下所示:
#define BAR(fmt, ...) printf(fmt, ##__VA_ARGS__)
但是有没有一种符合标准的方法来获得这种行为? 也许使用多个宏?
目前,## 版本似乎得到了很好的支持(至少在我的平台上),但我真的更愿意使用符合标准的解决方案。
先发制人:我知道我可以只写一个小函数。我正在尝试使用宏来做到这一点。
编辑:这是我为什么要使用 BAR() 的示例(虽然很简单):
#define BAR(fmt, ...) printf(fmt "\n", ##__VA_ARGS__)
BAR("here is a log message");
BAR("here is a log message with a param: %d", 42);
这会自动在我的 BAR() 日志记录语句中添加一个换行符,假设 fmt 始终是双引号 C 字符串。它不会将换行符作为单独的 printf() 打印,如果日志记录是行缓冲的并且来自多个异步源,这将是有利的。
【问题讨论】:
-
为什么首先使用
BAR而不是FOO? -
@GMan:我在最后加了一个例子
-
@GMan:阅读最后一句话(:
-
C2x 中的此功能 has been proposed for inclusion。
-
@zwol 提交给 WG14 looks like this 的最新版本,它使用基于
__VA_OPT__关键字的新语法。这是 C++ 的 has already been "adopted",所以我希望 C 会效仿。 (不知道这是否意味着它被快速跟踪到 C++17 或者它是否设置为 C++20)
标签: c c99 c-preprocessor variadic-macros