3

我有一个可变参数函数,它在我的应用程序中打印错误消息,其代码如下:

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()}

但这不能正确打印参数。

上面的宏定义有什么问题?

解决方法是什么?

4

5 回答 5

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_listin 函数方法。如果您希望定义驻留在头文件中,那么也许是静态内联函数?

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
}
于 2009-08-25T12:14:40.990 回答
1

这是一篇文章,其中包含一些关于宏中使用的变量参数的示例。看起来它应该做你正在寻找的东西。您可以__VA_ARGS__在宏中使用。

您使用的是哪个编译器?

于 2009-08-25T12:11:37.680 回答
0

许多编译器支持 GNU 风格的可变参数宏,如下所示:

#define error(format,args...) do { \
  fprintf(stderr, "error: " format "\n", ##args); \
  abort(); \
} while(0)

但是,如果您的目标是可移植性,请不要使用可变参数宏。

于 2009-08-25T12:13:24.013 回答
0

有一个通用扩展可以满足您的需求,只需编写:

#define error(args...) (fputs("Error: ",stdout),printf(args),puts(""))

C99 用户也可以说:

#define error(...) (fputs("Error: ",stdout),printf(__VA_ARGS__),puts(""))

但是使用有一些问题__VA_ARGS__。幸运的是,有一个 GCC 扩展来处理它,但随后您又回到了使用特定于编译器的扩展,并且该args...模式更广泛地可用。

于 2009-08-25T12:15:10.957 回答
0

宏不(还没有?)支持可变参数,无论如何,使用va_list在这里不起作用,它只适用于可变参数函数参数。

无论如何,您为什么要使用宏替换该功能(根据您的说法,它可以正常工作)?

于 2009-08-25T12:09:16.780 回答