如何在宏中使用vsprintf / vsnprintf?

时间:2011-06-25 13:38:01

标签: c++ gcc g++ log4cplus

我正在尝试编写一个宏来简化LOG4CPLUS的使用。但是在编写宏时我遇到了一些麻烦。

这是我的cpp文件中的内容:

Logger logger = Logger::getInstance("ManagerServer");

之后,我可以像这样记录一行:

LOG4CPLUS_ERROR(logger, logEvent);

我只想编写一个宏,而不是将logEvent更改为某个变量参数。并使用这样:

LogErr("failed");
LogErr("failed times %d", iTimes);

所以,我这样写:

#define LogErr(fmt, args...)\
    do {\
        char szBuf[MAX_LOG_BUFFER_SIZE];\
        memset(szBuf, 0, MAX_LOG_BUFFER_SIZE);  \
        vsnprintf(szBuf, MAX_LOG_BUFFER_SIZE, fmt, ##args); \
        LOG4CPLUS_ERROR(logger, szBuf);\
    } while(0)

但是当我编译的时候。 g ++给我这条消息:

  

错误:')'令牌

之前的预期主要表达式

有人可以帮助我吗?我真的很感激。

4 个答案:

答案 0 :(得分:2)

糟糕... C标签已被删除

当提供的参数不足(LogErr("failed"))时,问题在于宏的扩展。这在C中不起作用。

尝试添加虚拟参数

LogErr("failed", 0);
/* or better */
LogErr("%s", "failed");

此外,您无法在宏中使用v*函数,就像您尝试的那样:预处理器不知道变量参数,广告无法创建va_list类型的对象。


在C99中,一种方法可以做你想要做的事情

#include <stdio.h>
#include <string.h>

#define MAX_LOG_BUFFER_SIZE 100

#define LogErr(fmt, ...)                                      \
  do {                                                        \
    char szBuf[MAX_LOG_BUFFER_SIZE];                          \
    memset(szBuf, 0, MAX_LOG_BUFFER_SIZE);                    \
    snprintf(szBuf, MAX_LOG_BUFFER_SIZE, fmt, ##__VA_ARGS__); \
    /* LOG4CPLUS_ERROR(logger, szBuf); */                     \
  } while(0)

int main(void) {
  LogErr("err %d", 4);
  /*LogErr("failed");*/
  LogErr("%s", "failed");
  return 0;
}

注意:snprintf##__VA_ARGS

答案 1 :(得分:1)

你在args参数后缺少一个逗号。

#define LogErr(fmt, args, ...)\
                        ^

另外,我不知道g ++目前是否支持可变参数宏,它是C ++ 11的一个特性。 (我相信C编译器支持它们。)

答案 2 :(得分:1)

感谢pmg,Ferruccio和所有人。你们真的救了我!

这些代码在我的电脑上运行良好。好像我确实错过了vsnprintf和snprintf。

#define Log(fmt, args...) \
    do {\
        char szBuf[MAX_LOG_BUFFER_SIZE];\
        snprintf(szBuf, MAX_LOG_BUFFER_SIZE-1, fmt, ##args);\
        LOG4CPLUS_ERROR(logger, szBuf);\
    } while(0)

int main() {
    Log("Hello macro.");
    Log("Hello macro %d", 1);
    Log("Hello macro %s, %d", "foo", 2);

    return 0;
}

再次感谢!

答案 3 :(得分:0)

最近(1.1.0+)版本的Log4cplus支持使用printf样式的宏进行日志记录。您在OP中的示例如下所示:

LOG4CPLUS_ERROR_FMT(logger, "failed");
LOG4CPLUS_ERROR_FMT(logger, "failed times %d", iTimes);

如果您仍希望以不同方式重新实现,请参阅loggingmacros.h了解实施细节。