如何扩展宏并删除逗号

时间:2015-09-23 19:19:50

标签: c macros c-preprocessor variadic variadic-macros

例如,我想编写自己的printf()替代方法,但我必须对变量参数执行计算:

#define log(fmt_string, ...) my_log(fmt_string, pack_args(__VA_ARGS__), __VA_ARGS__)

其中pack_args(...) - 也是一个宏。 我该如何更改此代码以处理唯一的fmt_string存在场景?

log("Some message here");

2 个答案:

答案 0 :(得分:3)

P99我有两个宏

#define P00_ARG(                                               \
 _1, _2, _3, _4, _5, _6, _7, _8,                               \
 _9, _10, _11, _12, _13, _14, _15, _16,                        \
  ... etc ...                                                  \
 _153, _154, _155, _156, _157, _158, _159,                     \
 ...) _159
#define P99_HAS_COMMA(...) P00_ARG(__VA_ARGS__,                \
 1, 1, 1, 1, 1, 1, 1,                                          \
 1, 1, 1, 1, 1, 1, 1, 1,                                       \
  ... etc ....                                                 \
 1, 1, 1, 1, 1, 1, 0, 0)

您可以使用它来确定您的参数是否包含逗号(因此参数多于您的格式)或不具有(仅限格式)。然后,您可以使用它来构建对两个宏之一的调用:

#define log(...) log2(P99_HAS_COMMA(__VA_ARGS__), __VA_ARGS__)
#define log2(N, ...) log3(N, __VA_ARGS__)
#define log3(N, ...) log ## N(__VA_ARGS__)

#define log0(FMT)              /* your version with format only goes here */
#define log1(FMT, __VA_ARGS__) /* your version with more goes here */

答案 1 :(得分:2)

  

我应该如何将此代码更改为[处理]唯一的fmt_string存在场景?

在标准C中使用可变参数宏完全不能这样做。标准明确规定在调用可变参数宏时,调用中的参数应该多于宏定义中的参数(不包括......)" (C2011,6.10.0 / 4)。您可以通过将宏更改为...来允许宏只使用一个参数。

#define log(...) /* ... */

...但是你无法将格式字符串与其他参数分开 - 至少在没有重新引入你现在遇到的同样问题时也是如此。

如果您需要支持零长度变量参数列表,则需要使用真正的函数。