我有一个变量参数函数,它在我的应用程序中打印错误消息,其代码如下:
void error(char *format,...)
{ va_list args;
printf("Error: ");
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
printf("\n");
abort();
}
此功能在错误条件下使用如下:
error("invalid image width %d and image height %d in GIF file %s",wid,hei,name);
error()
函数是从具有不同参数的不同位置调用的(变量参数函数)。
功能方法正常。
现在,如果我必须将此功能转换为宏,我该怎么做?我试着这样做:
#define error(format) {va_list args;\
printf("Error: ");\
va_start(args, format);\
vfprintf(stderr, format, args);\
va_end(args);\
printf("\n"); abort()}
但是这不能正确打印参数。
上面的宏定义有什么问题?
修复是什么?
答案 0 :(得分:2)
如果编译器支持ISO样式可变参数宏,则可以定义宏:
#define error(...) \
fprintf(stderr, "Error: "); \
fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, "\n"); \
abort();
或者,如果您使用的是GCC,那么也会使用GNU样式的可变参数宏:
#define error(format, args...) \
fprintf(stderr, "Error: "); \
fprintf(stderr, format , ## args); \
fprintf(stderr, "\n"); \
abort();
有关详细信息,请参阅http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html
<强>更新强>
如果您的编译器没有可变宏支持,那么(差的?)替代方法是坚持功能方法中的va_list
。如果您希望定义驻留在头文件中,那么可能是静态内联函数?
static inline void error(const char *fmt, ...) {
#define PRINT_ERROR
va_list args;
fprintf(stderr, "Error: ");
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
fprintf(stderr, "\n");
abort();
#endif
}
答案 1 :(得分:1)
这是article with some examples on variable arguments used in a macro。它看起来应该做你想要的。您可以在宏中使用__VA_ARGS__
。
您使用的是哪种编译器?
答案 2 :(得分:0)
宏不(但是?)支持可变参数,无论如何,使用va_list
在这里不起作用,它只适用于可变参数函数参数。
为什么要用宏替换功能(根据你这样工作正常)?
答案 3 :(得分:0)
许多编译器都支持GNU样式的可变参数宏,如下所示:
#define error(format,args...) do { \
fprintf(stderr, "error: " format "\n", ##args); \
abort(); \
} while(0)
但是,如果您的目标是可移植性,请不要使用可变参数宏。
答案 4 :(得分:0)
有一个共同的扩展可以做你想要的,只需写:
#define error(args...) (fputs("Error: ",stdout),printf(args),puts(""))
C99用户也可以说:
#define error(...) (fputs("Error: ",stdout),printf(__VA_ARGS__),puts(""))
但some problems使用__VA_ARGS__
。幸运的是,有一个GCC扩展来处理它,但是你又回到了使用特定于编译器的扩展,并且args...
模式可以更广泛地使用。