Huc*_*kle 0 c macros verbosity
我想写一些我想象的是一个相当常见的宏.我想通过定义以下形式的一堆宏来模拟许多POSIX程序上重复的"-v"选项:
#define V1(str, ...) if(optv >= 1){printf("%s: "str,prog,__VA_ARGS__);}
int main(int argc, char* argv[])
{
// ... stuff ...
int i = 1;
V1("This contains a variable: %d\n",i);
}
// Output:
// ./program: This contains a variable: 1
Run Code Online (Sandbox Code Playgroud)
其中,optv计算命令行中找到的"-v"选项的数量,并prog包含程序名称(均未显示).这很好用,但问题是我必须使用变量.V1("Output")将生成编译器错误.我总是可以使用,V1("Output%s","")但应该有一个更清洁的解决方案.
GNU C预处理器有一个特殊功能,当没有参数填充可变参数部分时,可以通过将token-pasting操作符添加##到__VA_ARGS__以下内容来删除尾随逗号:
#define V1(str, ...) if(optv < 1); else printf("%s: "str,prog, ## __VA_ARGS__)
Run Code Online (Sandbox Code Playgroud)
或者,如果您希望完全符合C99,则可以将格式字符串参数合并到省略号中,但在这种情况下,您还需要重构代码,因为您希望prog在格式字符串和格式字符串之间包含额外参数.可变参数.像这样的东西可能会起作用:
#define V1(...) if(optv < 1); else myprintf(prog, __VA_ARGS__)
int myprintf(const char *prog, const char *fmt, ...)
{
// Print out the program name, then forward the rest onto printf
printf("%s: ", prog);
va_list ap;
va_start(ap, fmt);
int ret = vprintf(fmt, ap);
va_end(ap);
return ret;
}
Run Code Online (Sandbox Code Playgroud)
然后,V1("Output")展开到myprintf(prog, "Output")不使用任何非C99编译器扩展.
编辑
另请注意,我if在宏中反转了条件,因为如果在if没有括号的语句中调用宏,可能会出现一些奇怪的问题- 请参阅此常见问题解答以获取详细说明.