C 宏定义
我试图定义一个宏,其功能如下。调用1没有问题,但调用2提示编译器错误,因为第三个参数不可用。如何定义同时支持调用1和调用2的宏C 宏定义,c,macros,C,Macros,我试图定义一个宏,其功能如下。调用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
#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 */
在第二个宏展开中会得到一个额外的逗号,因为在宏定义中,
fmt
之后有一个无条件逗号
从宏定义中删除fmt
参数似乎可以解决问题;格式字符串随后成为\uu VA\u ARGS\uu
的一部分:
#define RDF_LOG(dbglevel, ...) (rdfDBG(dbglevel, " " __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");
#define RDF_LOG(dbglevel, fmt...) (rdfDBG(dbglevel, " " fmt))
void rdfDBG(int dbglevel, const char *fmt, ...) { /* printf debug message */ }
enum { kERROR };
void x(const char *pinfile);
void x(const char *pinfile)
{
RDF_LOG(kERROR, "Fail to open file %s\n", pinfile);
RDF_LOG(kERROR, "Insufficient Memory\n");
}
这扩展到:
void rdfDBG(int dbglevel, const char *fmt, ...) { }
(rdfDBG(kERROR, " " "Fail to open file %s\n", pinfile));
(rdfDBG(kERROR, " " "Insufficient Memory\n"));
顺便说一句,“
似乎要求格式为字符串文字(我修改的版本保留了这一点)。你确定要这么做吗?尽管这种情况很少见,但使用非文字格式字符串还是很有用的。GCC扩展
GCC有一个扩展来处理这个问题(注意,…
前面缺少逗号):
不正确(GCC扩展中不允许的引用\uu VA\u ARGS\uu
):
正确(未引用\uu VA\u ARGS\uu
):
可以看出我没有使用GCC扩展,因为我使用的一些编译器不是GCC
Adam在其评论中还提到了第二种(GCC特有的)机制:
#define RDF_LOG(dbglevel, fmt, ...) (rdfDBG(dbglevel, " " fmt, ## __VA_ARGS__))
void rdfDBG(int dbglevel, const char *fmt, ...) { /* printf debug message */ }
enum { kERROR };
void x(const char *pinfile);
void x(const char *pinfile)
{
RDF_LOG(kERROR, "Fail to open file %s\n", pinfile);
RDF_LOG(kERROR, "Insufficient Memory\n");
}
标准C99
否则,您必须使用C99标准机制:
#define RDF_LOG(dbglevel, ...) (rdfDBG(dbglevel, " " __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");
这基本上是欺骗或规避了这种情况下的问题。在一般情况下,C99需要一个逗号和至少一个参数。您的第一个示例不起作用。你确定你没有想到GCC扩展,如果你把
##
前置到uu VA_uargs_uu
并且零个参数匹配省略号,那么它会删除后面的逗号吗?例如,#定义RDF_日志(fmt,…)foo(fmt,###VA_参数)
结果为RDF_日志(“foo”)
=>foo(“foo”)
。
#define RDF_LOG(dbglevel, ...) (rdfDBG(dbglevel, " " __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");