【问题标题】:wrapping a C printf() call in a preprocessor directive在预处理器指令中包装 C printf() 调用
【发布时间】:2021-12-14 15:26:09
【问题描述】:

我正在尝试将 C 代码从一个平台移植到另一个平台并删除依赖项。

有一个名为dbg_out 的调试函数,其打印输出类似于printf()

原型是void dbg_out(int dbgMask, const char *pFormat, ...);

这是一个示例调用:dbg_out((5, "SerialDriver : (%04x-%08lx) \n", id, sn));

我想将此函数映射到正常的printf() 调用,但有一些问题。

到目前为止我已经尝试过了

void dbg_out (int dbgMask, const char *pFormat, ...)
__attribute__((format(printf, 2, 3)))
;    

我需要忽略第一个参数 dbgMask,只考虑其他参数。

我更喜欢使用预处理器来定义包装器。我会很感激这方面的帮助。

【问题讨论】:

  • 致电vprintf()

标签: c printf c-preprocessor wrapper preprocessor-directive


【解决方案1】:

您需要改用vprintf,才能使用未知参数

inline void dbg_out (int dbgMask, const char *pFormat, ...) {
  va_list ptr;
  va_start(ptr, pFormat);
  vprintf(pFormat, ptr);
  va_end(ptr);
}

【讨论】:

  • 谢谢
【解决方案2】:

使用宏

如果您想使用一个宏,将对dbg_out 的调用更改为对printf 的直接调用,您可以使用可变参数宏:

#define dbg_out(mask, ...) printf(__VA_ARGS__)

int main() {
  dbg_out(1, "%d", 12);
}

如果他们在你的问题中被称为双括号(例如dbg_out((5, "%d", 12)); ),那么你需要先解包:

#define EXPAND(mask, ...) (__VA_ARGS__)
#define dbg_out(...) printf EXPAND __VA_ARGS__

int main() {
  dbg_out((1, "%d", 12));
}

此外,如果您知道格式始终为字符串文字,您还可以将掩码添加到 printf 输出,例如:

#define dbg_out(mask, format, ...) printf("[Mask:%d]" format, mask, ##__VA_ARGS__)

int main() {
  dbg_out(1, "%d", 12);
}

双括号调用:

#define EXPAND(mask, format, ...) ("[Mask:%d]" format, mask, ##__VA_ARGS__)
#define dbg_out(...) printf EXPAND __VA_ARGS__ 

int main() {
  dbg_out((1, "%d", 12));
}

使用宏重定向到另一个函数

如果您无法更改 dbg_out 的实现,您可以使用宏将调用重定向到另一个执行该工作的函数:

#include <stdarg.h>

#define dbg_out(...) dbg_out_new(__VA_ARGS__) 

void dbg_out_new(int mask, const char* fmt, ...) __attribute__((format(printf, 2, 3)));
void dbg_out_new(int mask, const char* fmt, ...) {
  va_list va;
  va_start(va, fmt);
  vprintf(fmt, va);
  va_end(va);
}

int main() {
    dbg_out(1, "%d", 12);
}

如果用双括号调用,需要把宏改成:

#define dbg_out(...) dbg_out_new __VA_ARGS__

/* ... */

int main() {
    dbg_out((1, "%d", 12));
}

使用__attribute__(format()),您还可以获得参数的编译时类型检查的好处,就像在“使用宏”示例中一样。

改变功能

如果您可以编辑 dbg_out 函数实现,则可以将其替换为上述 dbg_out_new 实现。

但是,如果像您在问题中写的那样用双括号调用它,这将不起作用。

【讨论】:

  • 感谢所有这些。非常有帮助。在您的倒数第二个解决方案中,我收到以下没有意义的错误:error: expected ';'在'EXPAND'之前#define dbg_out(...) printf EXPAND VA_ARGS
  • @Engineer999 所有调用都有双括号吗?还是只有一些?我认为它要么总是双倍的,要么只是普通的单倍的。如果它们混合在一起,我将不得不调整我的示例来解决这个问题。
  • 嗨。是的,所有的电话肯定都有双括号,所以不确定这里发生了什么:)
  • @Engineer999 您是否使用带有“##”的更新版本?没有它们,如果只有一个没有附加参数的格式字符串,它将无法工作。如果它仍然不起作用,您能否分享导致问题的 dbg_out() 调用?
  • 感谢您的帮助。现在一切正常。那里有一些很棒的解决方案
猜你喜欢
  • 1970-01-01
  • 2020-03-21
  • 1970-01-01
  • 2010-09-23
  • 2014-04-13
  • 2023-03-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多