宏定义
我尝试定义一个宏,其功能如下。调用 1 没有问题,但调用 2 提示编译器错误,因为第三个参数不可用。如何定义一个同时支持调用1和调用2的宏?
#define RDF_LOG(dbglevel, fmt, ...) (rdfDBG(dbglevel, " " fmt, __VA_ARGS__))
void rdfDBG(int dbglevel, const char *fmt, ...) { /* printf debug message */ }
RDF_LOG(kERROR, "Fail to open file %s\n", pinfile); /* Call 1 */
RDF_LOG(kERROR, "Insufficient Memory\n"); /* call 2 , compiler -> error: expected expression before ')' token */
I tried to define a macro functioned as below. Call 1 has no problem, but Call 2 prompted compiler error because 3rd argument is not available. How to define a macro which support both call 1 and call 2?
#define RDF_LOG(dbglevel, fmt, ...) (rdfDBG(dbglevel, " " fmt, __VA_ARGS__))
void rdfDBG(int dbglevel, const char *fmt, ...) { /* printf debug message */ }
RDF_LOG(kERROR, "Fail to open file %s\n", pinfile); /* Call 1 */
RDF_LOG(kERROR, "Insufficient Memory\n"); /* call 2 , compiler -> error: expected expression before ')' token */
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您在第二个宏扩展中得到了一个额外的逗号,因为在宏定义中的
fmt
之后有一个无条件逗号。从宏定义中删除
fmt
参数似乎可以解决问题;然后格式字符串成为__VA_ARGS__
的一部分:这扩展为:
顺便说一句,看起来
" "
旨在要求格式为字符串文字(我修改过的版本保留了这一点)。您确定要这样做吗?虽然这种情况很少见,但使用非文字格式字符串可能会很有用。You're getting an extra comma in the second macro expansion, because you have an unconditional comma after
fmt
in the macro definition.Dropping the
fmt
parameter from the macro definition seems to fix the problem; the format string then becomes part of__VA_ARGS__
:This expands to:
Incidentally, it looks like the
" "
is intended to require the format to be a string literal (and my modified version preserves this). Are you sure you want to do that? Though it's rare, it can be useful to have a non-literal format string.GCC 扩展
GCC 有一个扩展来处理该问题(请注意
...
之前缺少逗号):不正确(GCC 扩展中不允许引用
__VA_ARGS__
):正确(不引用
__VA_ARGS__
):你可以看出我不使用 GCC 扩展 - 因为我使用一些不是 GCC 的编译器。
Adam 在他的评论中还提到了第二种(GCC 特定的)机制:
Standard C99
如果做不到这一点,您必须使用 C99 标准机制:
这基本上可以欺骗或规避此上下文中的问题。一般情况下,C99 需要一个逗号和至少一个参数。
GCC Extensions
GCC has an extension to handle that (note the missing comma before the
...
):Incorrect (references
__VA_ARGS__
which is not allowed in the GCC extension):Correct (not referencing
__VA_ARGS__
):You can tell I don't use the GCC extension - because I use some compilers that are not GCC.
There is also the second (GCC-specific) mechanism mentioned by Adam in his comment:
Standard C99
Failing that, you have to use the C99 standard mechanism:
This basically cheats or circumvents the problem for this context. In the general case, C99 requires a comma and at least one argument.