良好的详细宏 (C99)
我正在写一个我想象的相当常见的宏。我想通过定义一组以下形式的宏来模拟许多 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","")
但应该有一个更干净的解决方案。
I'm looking to write what I would imagine is a fairly common macro. I want to emulate the repeated "-v" options on many POSIX programs by defining a bunch of macros of the following form:
#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
where optv
counts the number of "-v" options found on the command line and prog
contains the program name (neither shown). This works well, but the problem is that I have to use a variable. V1("Output")
will generate a compiler error. I could always use V1("Output%s","")
but there should be a cleaner solution.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
GNU C 预处理器有一个特殊功能,可以让您删除结尾的逗号当没有参数通过在
__VA_ARGS__
前面添加标记粘贴运算符##
来填充可变参数部分时:或者,如果您希望保留完全 C99兼容,您可以将格式字符串参数合并到省略号中,但在这种情况下,您还需要重构代码,因为您希望在格式字符串和可变参数之间包含额外的
prog
参数。像这样的东西可能会起作用:然后,
V1("Output")
扩展为myprintf(prog, "Output")
而不使用任何非 C99 编译器扩展。编辑
另请注意,我反转了宏中的
if
条件,因为如果您在if
内调用宏,可能会出现一些奇怪的问题不带大括号的声明 - 请参阅此常见问题解答以获得详细的解释。The GNU C preprocessor has a special feature that lets you delete the trailing comma when there are no arguments filling the variadic portion by prepending the token-pasting operator
##
to__VA_ARGS__
:Alternatively, if you wish to remain fully C99 compliant, you could incorporate the the format string parameter into the ellipsis, but in this instance you'll also need to refactor your code since you want to include the extra
prog
parameter between the format string and the varargs. Something like this might work:Then,
V1("Output")
expands tomyprintf(prog, "Output")
without using any non-C99 compiler extensions.EDIT
Also note that I inverted the
if
condition in the macro, due to some weird issues that can arise if you invoke the macro inside anif
statement without braces—see this FAQ for a detailed explanation.为什么不为每个详细级别使用 2 个不同的宏?一种打印消息和变量,另一种只打印消息?
Why don't you use 2 different macros for each verbosity level; one which prints a message and variable, and one which just prints a message?
您可能应该为自己编写一个小的支持函数,以便可以干净地完成工作:
我假设
optv
和prog
都是全局变量。这些将进入标题(您不会将它们写在程序本身中,不是吗?)。该功能可以是:
其中没有火箭科学。您可以根据自己的喜好调整系统,允许选择信息的写入位置、刷新输出、确保末尾有换行符等。
You should probably write yourself a small support function so that you can do the job cleanly:
I assume that both
optv
andprog
are global variables. These would go into a header (you wouldn't write them out in the programs themselves, would you?).The function can be:
There's no rocket science in there. You can tweak the system to your heart's content, allowing a choice of where the information is written, flushing the output, ensuring there's a newline at the end, etc.
试试这个:
我相信这可以解决您所描述的问题,而最后的
else
解决了另一个问题。Try this:
I believe that fixes the problem you described, and the
else
at the end fixed another problem.