我正在寻找我想象的是一个相当常见的宏。我想通过定义以下形式的一堆宏来模拟许多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
其中optv
计算命令行中找到的“-v”选项的数量,prog
包含程序名称(均未显示)。这很好用,但问题是我有使用变量。 V1("Output")
将生成编译器错误。我总是可以使用V1("Output%s","")
,但应该有一个更清洁的解决方案。
答案 0 :(得分:5)
GNU C预处理器有一个special feature,当没有参数填充可变参数部分时,可以通过将令牌粘贴操作符##
添加到__VA_ARGS__
来删除尾随逗号:< / p>
#define V1(str, ...) if(optv < 1); else printf("%s: "str,prog, ## __VA_ARGS__)
或者,如果您希望完全符合C99,则可以将格式字符串参数合并到省略号中,但在这种情况下,您还需要重构代码,因为您要包含额外的{{1}格式字符串和varargs之间的参数。这样的事情可能有用:
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;
}
扩展为V1("Output")
,而不使用任何非C99编译器扩展。
修改强>
另请注意,我在宏中反转了myprintf(prog, "Output")
条件,因为如果在没有大括号的if
语句中调用宏,可能会出现一些奇怪的问题 - 请参阅this FAQ详细解释。
答案 1 :(得分:1)
为什么不为每个详细级别使用2个不同的宏;一个打印消息和变量,一个打印消息?
答案 2 :(得分:1)
你应该写一个小的支持功能,这样你就可以干净利落地完成工作:
extern void vb_print(const char *format, ...);
#define V1(...) do { if (optv >= 1) vb_print(__VA_ARGS__); } while (0)
我假设optv
和prog
都是全局变量。这些会进入标题(你不会在程序中自己写出来,不是吗?)。
该功能可以是:
#include <stdio.h>
#include <stdarg.h>
extern const char *prog;
void vb_print(const char *format, ...)
{
va_list args;
va_start(args, format);
printf("%s:", prog);
vprintf(format, args);
va_end(args);
}
那里没有火箭科学。您可以根据自己的内容调整系统,允许选择信息的写入位置,刷新输出,确保最后有换行符等。
答案 3 :(得分:0)
试试这个:
#define V1X(str, ...) if(optv >= 1) {printf("%s: "str,prog,__VA_ARGS__);} else
#define V1(...) V1X(__VA_ARGS__,0)
我认为这可以解决您描述的问题,最后else
解决了另一个问题。