无法从另一个调用一个#define宏

时间:2015-02-13 17:32:19

标签: c

我有这些行

#define LOG(fp, fmt, ...) fprintf(fp, "%s:%d: "fmt, __FILE__, __LINE__, ## __VA_ARGS__) 
#define OUT(fmt, ...) LOG(stdout, fmt, __VA_ARGS__) 

编译器显示OUT错误。如何从OUT中调用LOG?

错误讯息:

  1. 在LOG中的')'标记之前的预期表达式
  2. 当我将其用作OUT("Hello world"); 时,
  3. 扩展错误

2 个答案:

答案 0 :(得分:3)

简短的解释是因为我从评论中得到了这些代码:## ##__VA_ARGS__是预处理器的非标准扩展(最初来自gcc,现在也得到了clang的支持)。它的作用是如果在没有可变参数的情况下调用可变参数宏,则删除多余的前一个逗号。也就是说,

#define FOO(bar, ...) foo(bar, __VA_ARGS__)

无法使用一个参数调用,因为它会扩展为foo(argument,)

#define FOO(bar, ...) foo(bar, ##__VA_ARGS__)

可以,因为逗号被静默删除,扩展名为foo(argument)

因此,您的问题的解决方案是使用

//                                     vv--- these are important here
#define OUT(fmt, ...) LOG(stdout, fmt, ##__VA_ARGS__) 

否则,在只有一个参数的OUT扩展中,__VA_ARGS__中的LOG不会为空,因为它是从

扩展的
LOG(stdout, "Hello, world.",)

而不是

LOG(stdout, "Hello, world.")

...而##__VA_ARGS__之前的LOG将无效。您收到编译器消息,因为LOG的扩展中有一个额外的逗号(fprintf调用以,)结尾)。

Link to specifics

答案 1 :(得分:0)

...中的OUT(fmt, ..)意味着需要传递至少一个参数,然后只传递fmt。例如:

OUT("%s", "Hello World");

如果这样做##没用,宏看起来应该是这样的:

#define LOG(fp, fmt, ...) fprintf((fp), "%s:%d: "fmt, __FILE__, __LINE__, __VA_ARGS__) 
#define OUT(fmt, ...) LOG(stdout, fmt, __VA_ARGS__)