问题描述
我有一个日志宏和一个函数,我希望它们具有相同的名称,这样当我错过宏的标题时,程序仍然会构建(通过 C 隐式函数 声明)。
我试过了:
/* Declare function. */
void logmsg(const char *fmt,...) __attribute__((format(printf,1,2)));
/* Declare macro (with the same name). */
#define logmsg(fmt,...) \
logmsg(fmt,##__VA_ARGS__)
但是这会因编译错误而失败:
In file included from util.c:53:
../lib/util.h:296:13: error: expected identifier or ‘(’ before ‘do’
296 | do { if (1) (logmsg(fmt,##__VA_ARGS__)); } while (0)
| ^~
util.c:248:6: note: in expansion of macro ‘logmsg’
248 | void logmsg(const char *fmt,...)
| ^~~~~~
../lib/util.h:296:59: error: expected identifier or ‘(’ before ‘while’
296 | do { if (1) (logmsg(fmt,##__VA_ARGS__)); } while (0)
| ^~~~~
util.c:248:6: note: in expansion of macro ‘logmsg’
248 | void logmsg(const char *fmt,...)
我怎样才能实现我的目标?
编辑:
我已经通过 indirect self-reference of macro identifier 解决了这个问题,如下所示:
void logmsg(const char *fmt,2)));
#define log_impl(specarg,fmt,...) \
logmsg(fmt,##__VA_ARGS__)
#define logmsg(fmt,...) \
log_impl(msg,##__VA_ARGS__)
msg
的 log_impl()
arg 不是必需的,但我已经隐藏了代码,无法对其进行确定。
解决方法
您需要防止在 logmsg
函数的声明及其定义中扩展 logmsg
宏。
无论您对宏定义的排序和引用 logmsg
函数的实际 C 代码如何始终使用括号括住对 logmsg
函数的引用,什么都应该起作用:
void (logmsg)(const char *fmt,...) __attribute__((format(printf,1,2)));
void (logmsg)(const char *fmt,...)
{
//...
}
,
在定义名为 logmsg
的函数时,宏替换发生在源文件中。由于此宏仅在调用函数时有效,因此最终会出现语法错误。此时您需要取消定义宏:
#undef logmsg
void logmsg(const char *fmt,...)
{
...