为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C
湖上湖 2019-11-05 15:59:36
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()打印,如果日志记录是行缓冲的并且异步地来自多个源,则这是有利的。
查看完整描述

3 回答

?
繁星coding

TA贡献1797条经验 获得超4个赞

这不是一个通用的解决方案,但是对于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中。


查看完整回答
反对 回复 2019-11-05
  • 3 回答
  • 0 关注
  • 2152 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号