【问题标题】:How do I use variadic arguments with printf in a macro?如何在宏中使用带有 printf 的可变参数?
【发布时间】:2018-02-07 05:46:43
【问题描述】:

我找不到将第一个 printf 合并到第二个的方法:

unsigned get_time_now(void) {return 1;}
#define DEBUG_PRINT 1
#define debug_tcprintf(fmt, ...) do { \
            if (DEBUG_PRINT) { \
                unsigned p_time_now = get_time_now(); \
                printf ("%u ms ", p_time_now); \
                printf(fmt, __VA_ARGS__); \
            } \
        } while (0)

我需要完成此操作以获得原子 debug_tcprintf。上面的宏取自this Stack Overflow question

我正在编写在 XMOS 多逻辑核处理器上运行的 XC 代码。它编译 XC、C 和 C++,但代码示例来自 C 代码部分。它与 XC 类似,只是它在语言中定义了一个计时器。

如果无法将两者合并到一个 printf 中,一个选项可能是创建一个字符串并使用 sprintf 代替?我宁愿不要,因为这样的数组很容易溢出。

【问题讨论】:

  • 对于初学者,为什么不直接printf("%u ms " fmt, p_time_now, __VA_ARGS__);
  • 是的,已删除评论。我明白你在做什么。 “原子” printf 声明让我挑了挑眉。这对我来说意味着不同的东西:)
  • @MichaelDorgan:当然,在 OP 意识到不存在这样的事情之前需要更长的时间。
  • 等一下,我加了一个逗号。立即测试
  • @ØyvindTeig: works for me

标签: c printf c-preprocessor variadic-macros


【解决方案1】:

您需要使用字符串连接和token pasting。请注意,在下面的 sn-p 中,第一个字符串文字后没有逗号——这是故意的。

#define debug_tcprintf(fmt, ...) do { \
    if (DEBUG_PRINT_HTTPD) { \
        unsigned p_time_now = get_time_now (); \
        printf ("%u ms " fmt, p_time_now, ##__VA_ARGS__); \
    } \
} while (0)

字符串连接允许您将"%u ms " 部分添加到提供的格式字符串中。令牌粘贴(## 运算符)说明了在调用宏时可能会使用或不使用其他可变参数(不仅仅是格式字符串)。

这仅在您使用字符串文字作为格式字符串调用宏时才有效。


附录:此示例中使用标记粘贴的方式实际上是标准 C 预处理器的 gcc 扩展。如果您不使用 gcc 编译器,则可能需要省略 ## 运算符。这样做的缺点是你不能只用一个参数调用你的宏。例如,debug_tcprintf ("hello world") 将不起作用。一个简单的解决方法是在这种情况下使用debug_tcprintf ("%s", "hello world")

【讨论】:

  • 我还会删除 p_time_now 临时变量 - 如果在发布版本中重新定义了 printf(),它不会做任何事情并且可能会导致警告。
  • 如果传入的格式不是字符串文字,则字符串连接和标记粘贴将不起作用。
  • @AndrewHenle:没错,但格式字符串可能永远不会是文字以外的任何东西。
  • @AndrewHenle 这就是为什么我的回答说“这仅在您使用字符串文字作为格式字符串调用宏时才有效。”
  • 是的,我知道。但是使用 debug_tcprintf ("%s", "Hello World\n");一旦我习惯了。
猜你喜欢
  • 2022-01-20
  • 1970-01-01
  • 2021-05-30
  • 1970-01-01
  • 1970-01-01
  • 2022-08-19
  • 2021-06-12
  • 2015-11-09
  • 1970-01-01
相关资源
最近更新 更多