在预处理器指令中包装 C printf() 调用
wrapping a C printf() call in a preprocessor directive
我正在尝试将 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
才能使用未知参数
inline void dbg_out (int dbgMask, const char *pFormat, ...) {
va_list ptr;
va_start(ptr, pFormat);
vprintf(pFormat, ptr);
va_end(ptr);
}
使用宏
如果您想使用宏将对 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
实现。
但是,如果像您在问题中写的那样用双括号调用它,这将不起作用。
我正在尝试将 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
才能使用未知参数
inline void dbg_out (int dbgMask, const char *pFormat, ...) {
va_list ptr;
va_start(ptr, pFormat);
vprintf(pFormat, ptr);
va_end(ptr);
}
使用宏
如果您想使用宏将对 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
实现。
但是,如果像您在问题中写的那样用双括号调用它,这将不起作用。