使 C 宏在结果中将自身替换为函数调用?

问题描述

我有一个日志宏和一个函数,我希望它们具有相同的名称,这样当我错过宏的标题时,程序仍然会构建(通过 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__)

msglog_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,...)
{
    ...

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...