【问题标题】:sprintf with elipses in C for macro definition results in compilation error用于宏定义的 C 中带有省略号的 sprintf 会导致编译错误
【发布时间】:2021-02-21 16:59:15
【问题描述】:

我正在定义一个宏来通过 UART 打印一些调试,但我遇到了问题。编译器不喜欢我在 sprintf 语句中使用省略号:

#define LOG_INFO(_str, ...)  { char * _buf[384] = {0}; sprintf(*_buf, _str, ...); UART2_Write((void*)_buf[0], sizeof(_buf)); }

结果...

../src/config/default/log_util.h:40:77: error: expected expression before '...' token

在 sprintf 语句中指明它的用途。我不知道我是不是解错了,或者这是编译器的限制,尽管据说编译器(XC32)可以处理这种事情。

对代码的任何更正或解决方法的建议将不胜感激。

【问题讨论】:

  • 欢迎来到 StackOverflow!请使用tour 并阅读“How to Ask”。然后回来edit你的问题,展示你试图解决问题的方法。您是否查阅了预处理器的手册如何使用可变参数?
  • char * _buf[384]; 是一个由 384 个指向 char 的指针组成的数组。要拥有 384 个字符的缓冲区,请删除星号并使用 char _buf[384];

标签: c printf


【解决方案1】:

您的宏存在多个问题:

  • 您不能使用... 来扩展宏变量参数列表。为此请使用__VA_ARGS__
  • 包含格式字符串以涵盖参数列表为空的情况。
  • _buf 定义为常规char 数组,而不是指针数组。
  • use snprintf` 防止缓冲区溢出
  • strlen(_buf) 传递给UART2_Write(),而不是整个数组大小。
  • 将代码包装在 do / while 循环中,以便 LOG_INFO("hello"); 展开为单个语句。

这是修改后的版本:

#define LOG_INFO(...)  do { char _buf[384]; snprintf(_buf, sizeof _buf, __VA_ARGS__); \ 
                            UART2_Write((void *)_buf, strlen(_buf)); } while (0)

请注意,无需将其定义为宏。您可以改用函数:

#include <stdarg.h>
#include <stdio.h>

int LOG_INFO(const char *format, ...) {
    va_list ap;
    va_start(ap, format);
    char buf[384];
    size_t len = vsnprintf(buf, sizeof buf, format, ap);
    va_end(ap);
    if (len > sizeof(buf) - 1)
        len = sizeof(buf) - 1;
    UART2_Write((void *)buf, len);
    return len;
}

【讨论】:

  • 非常感谢。我喜欢使用宏的原因是因为我可以定义多个日志级别并相应地定义 uart 打印函数,即。 '#if LOG_LEVEL_INFO #define LOG_INFO(...) 做一些事情 #else #define LOG_INFO(...) //什么都不做 #endif'
  • @TristanRitchie:即使有函数,你仍然可以使用宏绕过函数调用:#if LOG_LEVEL_INFO == 0 #define LOG_INFO(...) /* do nothing */ #endif,并在函数定义中禁用宏:int (LOG_INFO)(const char *format, ...) { ... }
【解决方案2】:

在宏的主体中将 ... 替换为 __VA_ARGS__

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-21
    • 2019-09-01
    相关资源
    最近更新 更多