Vor*_*rac 28 c logging c99 word-wrap
这听起来有点像面试问题,但实际上是一个实际问题.
我正在使用嵌入式平台,并且仅提供这些功能的等价物:
此外,printf()实现(和签名)很可能在不久的将来发生变化,因此对它的调用必须驻留在一个单独的模块中,以便以后易于迁移.
鉴于这些,我可以在一些函数或宏中包装日志记录调用吗?目标是我的源代码THAT_MACRO("Number of bunnies: %d", numBunnies);
在一千个地方调用,但是只能在一个地方看到对上述函数的调用.
编译器:arm-gcc -std = c99
Ser*_* L. 54
有两种方法可以做到这一点:
Variadric宏
#define my_printf(...) printf(__VA_ARGS__)
Run Code Online (Sandbox Code Playgroud)转发的功能 va_args
#include <stdarg.h>
#include <stdio.h>
void my_printf(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
}
Run Code Online (Sandbox Code Playgroud)还有vsnprintf
,vfprintf
无论你能想到什么stdio
.
lda*_*v1s 36
既然你可以使用C99,我将它包装在一个可变的宏中:
#define TM_PRINTF(f_, ...) printf((f_), __VA_ARGS__)
#define TM_SNPRINTF(s_, sz_, f_, ...) snprintf((s_), (sz_), (f_), __VA_ARGS__)
Run Code Online (Sandbox Code Playgroud)
因为你没有说你有vprintf
或类似的东西.如果你确实有这样的东西,你可以将它包装在谢尔盖L在他的答案中提供的功能中.
上述TM_PRINTF不适用于空的VA_ARGS列表.至少在GCC中可以写:
#define TM_PRINTF(f_, ...) printf((f_), ##__VA_ARGS__)
Run Code Online (Sandbox Code Playgroud)
如果__VA_ARGS__
为空,则两个##符号删除它们前面的多余逗号.
unw*_*ind 11
如果您可以将呼叫包含在两个括号中,您可以这样做:
#define THAT_MACRO(pargs) printf pargs
Run Code Online (Sandbox Code Playgroud)
然后使用它:
THAT_MACRO(("This is a string: %s\n", "foo"));
^
|
OMG
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为从预处理器的角度来看,整个参数列表成为一个宏参数,用括号替换.
这比仅仅做得好
#define THAT_MACRO printf
Run Code Online (Sandbox Code Playgroud)
因为它允许你定义它:
#define THAT_MACRO(pargs) /* nothing */
Run Code Online (Sandbox Code Playgroud)
这将"吞噬"宏参数,它们永远不会成为编译代码的一部分.
更新当然在C99中这种技术已经过时,只需使用可变参数宏并感到高兴.
#define TM_PRINTF(f_, ...) printf((f_), ##__VA_ARGS__)
Run Code Online (Sandbox Code Playgroud)
该##
令牌将启用使用率TM_PRINTF("aaa");