我正在实现一种日志记录调度程序,即int32_t logf(const char *fmt, ...);
,它输出到不同的日志记录目标,具体取决于它编译的选项。
以下是摘录摘录。
int32_t logf(const char *fmt, ...)
{
va_list va;
i32 res;
va_start(va, fmt);
res = S_PASS;
#ifdef LOG_UART
res = Uart_vprintf(fmt, va);
if (res != S_PASS) goto exit;
#endif /* LOG_UART */
#ifdef LOG_SYS
res = System_vprintf(fmt, va);
if (res != S_PASS) goto exit;
#endif /* LOG_SYS */
exit:
va_end(va);
return res;
}
现在......如果没有给出选项,记录器将(实际上是打算)是一个空记录器。但是,我是否还需要调用va_start()
和va_end()
?
换句话说(忽略-Wunused-label一秒),这是正确的:
int32_t logf(const char *fmt, ...)
{
va_list va;
i32 res;
va_start(va, fmt);
res = S_PASS;
exit:
va_end(va);
return res;
}
......还是这个?
int32_t logf(const char *fmt, ...)
{
i32 res;
res = S_PASS;
return res;
}
更新
生成的 empty 函数实现不能被像#define logf(fmt, ...) S_PASS;
这样的函数式宏替换。
现有代码库已定义typedef int32_t(*logFunc)(const char *fmt, ...);
,因此指向logf的指针必须是可存储的。
答案 0 :(得分:3)
如果没有日志记录已启用,我建议您只使用一个空函数,或者可能是一个扩展为S_PASS
的可变参数宏。
也许像
#if defined(LOG_UART) || defined(LOG_SYS)
inline int32_t logf(const char *fmt, ...)
{
// Your original code here...
}
#else
# define logf(x, ...) S_PASS
#endif
以上是您在标题中定义的功能。如果您的标题中只有声明,并且源文件中的定义几乎相同。
标题文件:
#if defined(LOG_UART) || defined(LOG_SYS)
int32_t logf(const char *fmt, ...);
#else
# define logf(x, ...) S_PASS
#endif
源文件:
#if defined(LOG_UART) || defined(LOG_SYS)
inline int32_t logf(const char *fmt, ...)
{
// Your original code here...
}
#endif
在你对函数指针的评论之后,最好的解决方案可能是有一个内联函数函数只 return
S_PASS`:
#if defined(LOG_UART) || defined(LOG_SYS)
int32_t logf(const char *fmt, ...);
#else
inline int32_t logf(const char *fmt, ...) { return S_PASS; }
#endif
答案 1 :(得分:1)
这有点没有实际意义,因为当你提出仅可变功能时,你会在脚下拍摄自己。你的可变函数应该始终是va_list
一个的包装器:
int32_t vlogf(const char *fmt, va_list va);
int32_t logf(const char *fmt, ...)
{
int32_t res;
va_list va;
va_start(va, fmt);
res = vlogf(fmt, va);
va_end(va);
}
此外,您不应该使用相同的va_list
两次,因此如果定义了两个宏,则需要va_copy
它:
int32_t vlogf(const char *fmt, va_list va)
{
i32 res;
res = S_PASS;
#if defined(LOG_UART) && defined(LOG_SYS)
/*Can't use the same va_list twice: */
/*If both are defined, need to use va_copy*/
{
va_list va2;
va_copy(va2, va);
res = Uart_vprintf(fmt, va);
if (res != S_PASS) goto exit2;
res = System_vprintf(fmt, va);
exit2:
va_end(va2);
}
if (res != S_PASS) goto exit;
#elif defined(LOG_UART)
res = Uart_vprintf(fmt, va);
if (res != S_PASS) goto exit;
#elif defined(LOG_SYS)
res = System_vprintf(fmt, va);
if (res != S_PASS) goto exit;
#endif /* LOG_SYS */
exit:
return res;
}