You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何同签名的可变参数宏TRACE编译失败而ASSERT正常?

问题

我定义了两个可变参数宏,其中ASSERT可正常编译,但TRACE编译失败:

#define ASSERT(x, ...)           assert_log(x, __FILE__, __LINE__, __VA_ARGS__)
#define TRACE (x, ...)           trace(x, __FILE__, __LINE__, __VA_ARGS__)

报错信息:

libs/defs.h:16:71: error: __VA_ARGS__ can only appear in the expansion of a C99 variadic macro [-Werror]
   16 |         #define TRACE (x, ...)           trace(x, __FILE__, __LINE__, __VA_ARGS__)
      |                                                                       ^

两个宏对应的函数签名一致:

void assert_log(int, const char*, int, const char* , ...);
void trace(int, const char*, int, const char* , ...);

编译选项:

CFLAGS= \
    -Wextra \
    -Werror \
    -Wall \
    -Wfloat-equal \
    -Wundef \
    -Wshadow \
    -Wcast-align \
    -Wstrict-prototypes \
    -Wswitch-enum \
    -Wformat=2 \
    -Werror=pointer-arith \
    -Wuninitialized \
    -pedantic \
    -std=c17 \
    -DDEBUG=1 \
    -g \
    -Og

既然函数签名相同,我无法理解GCC为何报错?

问题原因与解决方法

问题出在TRACE宏的定义语法上:#define TRACE (x, ...) 中TRACE和括号之间多了一个空格。

C语言中,宏定义的名称和参数列表的左括号必须紧挨着,不能有空格。如果加了空格,预处理器会把TRACE解析成一个无参数宏,后面的(x, ...)会被当成宏展开内容的一部分,此时__VA_ARGS__并不处于可变参数宏的上下文里,自然触发编译错误。

对比ASSERT的定义#define ASSERT(x, ...),名称和括号没有空格,符合可变参数宏的语法要求,所以能正常编译。

只需要去掉TRACE和括号之间的空格,修正后的宏定义如下:

#define TRACE(x, ...)           trace(x, __FILE__, __LINE__, __VA_ARGS__)

内容的提问来源于stack exchange,提问作者Denis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 05:33:15