繁体   English   中英

宏定义

[英]macro definition

我试图定义一个功能如下的宏。 调用1没有问题,但调用2提示编译器错误,因为第3个参数不可用。 如何定义一个支持call 1和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 */

你在第二个宏扩展中得到一个额外的逗号,因为你在宏定义中的fmt之后有一个无条件的逗号。

从宏定义中删除fmt参数似乎可以解决问题; 格式字符串然后成为__VA_ARGS__一部分:

#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");

这扩展到:

void rdfDBG(int dbglevel, const char *fmt, ...) { }

(rdfDBG(kERROR, " " "Fail to open file %s\n", pinfile));
(rdfDBG(kERROR, " " "Insufficient Memory\n"));

顺便说一下,看起来" "意图要求格式为字符串文字(我的修改版本保留了这个)。 你确定要这么做吗? 尽管很少见,但是使用非文字格式字符串会很有用。

GCC扩展

GCC有一个扩展来处理(注意...之前缺少的逗号):

不正确(引用GCC扩展中不允许的__VA_ARGS__ ):

#define RDF_LOG(dbglevel, fmt ...) (rdfDBG(dbglevel, " " fmt, __VA_ARGS__))

正确(不引用__VA_ARGS__ ):

#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");
}

你可以告诉我不使用GCC扩展 - 因为我使用了一些非GCC的编译器。

亚当在评论中也提到了第二种(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需要逗号和至少一个参数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM