【问题标题】:Variadic macros with 0 arguments in C99C99 中具有 0 个参数的可变参数宏
【发布时间】:2011-04-04 08:00:27
【问题描述】:

我有一些调试代码,如下所示:

#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define AT __FILE__ ":" TOSTRING(__LINE__)
void __my_error(const char*loc, const char *fmt, ...);
#define my_error(fmt, ...) __my_error(AT, fmt, ##__VA_ARGS__)

使用了最后一个宏,因此我可以将该位置插入到调试输出中,以了解错误发生的位置。但是,当我这样调用函数时:

my_error("Uh oh!");

我希望喜欢我的代码是 C99,所以我发现当它编译时,我收到以下错误:

error: ISO C99 requires rest arguments to be used

我知道我可以通过改变调用来解决这个问题

my_error("Uh oh!", NULL);

但是有什么办法可以让这看起来不那么难看?谢谢!

【问题讨论】:

  • 您可能还想看看这个答案:stackoverflow.com/questions/1644868/…(单参数部分)
  • 在定义自己的名称时要小心,其中包含两个相邻的下划线:所有这些名称都由标准保留(因此库、编译器或标准更新可能会以某种方式使用它们)。

标签: macros c99 variadic


【解决方案1】:

我看到了这个问题的两种解决方案。 (如果算上“坚持使用 gcc”,则为三个)。

额外的特殊情况宏

当你想打印一个固定的字符串时添加一个新的宏。

#define my_errorf(str) my_error(str, NULL)

专业版:最少的额外代码。
缺点:使用错误的宏很容易(但至少你在编译时注意到了这一点)。

fmt 放在'...'内

可变参数宏只能有 __VA_ARGS__ 作为参数(与可变参数函数不同)。因此,您可以将 fmt 参数放在 __VA_ARGS__ 中并更改您的函数。

void __my_error(const char *loc, ...);
#define my_error(...) __my_error(AT, __VA_ARGS__)

Pro:所有错误消息的一种语法/宏。
Con:需要重写您的 __my_error 函数,这可能是不可能的。

【讨论】:

  • 是的,这两个功能是相同的(我的错字)。我会尝试解决方案 2,看看我是否可以解决这个问题。对于本质上是私有的事物(例如 __my_error 函数,它永远不应该被直接调用),您对命名约定有何建议?
  • @Michael 让我知道结果如何。我通常在宏名称中添加一个“_suffix”,例如my_error_realmy_error_private 或只是my_error_x(来自“eXpanded”)。
  • Vararg 宏可以 不仅有 VA_ARGS 作为参数。例如,您可以传递 FILE*(用于 fprintf)或 char[](用于 snprintf)。只是 ... 必须匹配至少一个参数,至少在 gcc 对 C99 的解释中。
  • 这些是解决方法,不是禁用警告的方法:(
  • fmt 放入... 将阻止您在格式字符串前添加和附加。
猜你喜欢
  • 1970-01-01
  • 2014-07-23
  • 1970-01-01
  • 2017-12-08
  • 2013-05-21
  • 1970-01-01
  • 2011-04-03
  • 1970-01-01
  • 2011-07-14
相关资源
最近更新 更多