ANSI C中的变量宏替代方案

时间:2014-12-26 23:38:24

标签: c c89 variadic-macros

我知道在C99(以及通过GNU扩展)中添加了可变参数宏。我一直想知道ANSI C中是否有一个不错的选择。

我想出了类似的东西,但它仍然有点尴尬:

void log_info(const char *file, int line, const char *fmt, ...)
{
#ifdef DEBUG
    va_list ap;
    char newfmt[1024] = { 0 };
    va_start(ap, fmt);
    sprintf(newfmt, "[INFO] (%s:%d): %s\n", file, line, fmt);
    vfprintf(stderr, newfmt, ap);
    va_end(ap);
#endif
}

这样就可以这样调用:

log_info(__FILE__, __LINE__, "info message: %s %d", "helloworld", 12);

这种方法没有错,但是我想知道是否有更好的方法呢?例如。无需每次都指定文件/行。

我很感激任何反馈。 :)

编辑:按ANSI C,我的意思是C89。

编辑:下面的答案很好,但我相信它需要运行打印命令twise,它可能会带来一些线程安全问题。另一种选择可能是使用define来最小化输入(也非常难看):

#define __FL__ __FILE__, __LINE__

然后运行命令:

log_info(__FL__, "info message: %s %d", "helloworld", 12);

2 个答案:

答案 0 :(得分:16)

它有点难看,但括号中的逗号分隔表达式序列可以视为单个参数。

一个例子:

#include <stdio.h>

#define LOG(args) (printf("LOG: %s:%d ", __FILE__, __LINE__), printf args)

int main(void) {
    LOG(("Hello, world\n"));
    int n = 42;
    LOG(("n = %d\n", n));
    return 0;
}

输出:

LOG: c.c:6 Hello, world
LOG: c.c:8 n = 42

请注意,这需要在呼叫中添加一组额外的括号。

答案 1 :(得分:3)

这是一个更加丑陋的选项,但是使用单一调用printf:

#define PROMPT "[INFO] (%s:%d): "
#define FL __FILE__, LINE__

#define DEBUG0(fmt) printf(PROMPT fmt, FL);
#define DEBUG1(fmt, a1) printf(PROMPT fmt, FL, a1);
#define DEBUG2(fmt, a1, a2) printf(PROMPT fmt, FL, a1, a2);
#define DEBUG3(fmt, a1, a2, a3) printf(PROMPT fmt, FL, a1, a2, a3);

等等,直到用宏调用宏的大多数参数。