不定长参数宏
2026/8/24大约 1 分钟
C语言不定长参数宏
不定长参数宏就是:
宏的参数个数可以变化。
核心依靠:
...和:
__VA_ARGS__一、最基本写法
#define LOG(fmt, ...) printf(fmt, __VA_ARGS__)调用:
LOG("value = %d", 42);展开后相当于:
printf("value = %d", 42);其中:
fmt → 固定参数
... → 可变参数
__VA_ARGS__ → 代表所有可变参数二、没有可变参数怎么办?
直接这样写:
#define LOG(fmt, ...) printf(fmt, __VA_ARGS__)
LOG("hello");展开后会出现:
printf("hello", );多了一个逗号。
GCC 可以用:
#define LOG(fmt, ...) \
printf("[LOG] " fmt "\n", ##__VA_ARGS__)这样:
LOG("value = %d", 42);
LOG("hello");分别展开为:
printf("[LOG] value = %d\n", 42);
printf("[LOG] hello\n");##__VA_ARGS__ 是 GCC 扩展,作用是:
可变参数为空时,同时去掉前面的逗号。
三、嵌入式中最常见:日志宏
#define LOG(fmt, ...) \
printf("[%s:%d] " fmt "\n", \
__FILE__, __LINE__, ##__VA_ARGS__)使用:
LOG("UART init");
LOG("RX len = %d", len);输出类似:
[main.c:20] UART init
[uart.c:35] RX len = 16这样可以统一给日志增加:
文件名
行号
时间戳
日志等级四、最终记忆
#define LOG(fmt, ...)
↓
可变参数宏
__VA_ARGS__
↓
代表所有可变参数
##__VA_ARGS__
↓
GCC扩展
↓
参数为空时去掉多余逗号核心:
...接收可变参数,__VA_ARGS__把它们展开出来。
嵌入式中最常见用途:
封装统一的调试日志接口。

