GCC的## __ VA_ARGS__技巧的标准替代方法?

C99中可变参数宏的空参数存在一个众所周知的 问题。


例:


#define FOO(...)       printf(__VA_ARGS__)

#define BAR(fmt, ...)  printf(fmt, __VA_ARGS__)


FOO("this works fine");

BAR("this breaks!");

BAR()根据C99标准,上面的使用确实是不正确的,因为它将扩展为:


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);

假定fmt始终是双引号的C字符串,这会自动向我的BAR()记录语句添加换行符。它不会将换行符作为单独的printf()打印,如果日志记录是行缓冲的并且异步地来自多个源,则这是有利的。


湖上湖
浏览 2153回答 3
3回答

繁星coding

这不是一个通用的解决方案,但是对于printf,您可以添加一个换行符,例如:#define BAR_HELPER(fmt, ...) printf(fmt "\n%s", __VA_ARGS__)#define BAR(...) BAR_HELPER(__VA_ARGS__, "")我相信它会忽略格式字符串中未引用的任何其他参数。因此,您甚至可以摆脱:#define BAR_HELPER(fmt, ...) printf(fmt "\n", __VA_ARGS__)#define BAR(...) BAR_HELPER(__VA_ARGS__, 0)我不敢相信没有标准方法即可批准C99。AFAICT该问题也存在于C ++ 11中。
打开App,查看更多内容
随时随地看视频慕课网APP