C语言 ##__VA_ARGS__
C 语言中 __VA_ARGS__ 是一个可变参数的宏,是新的 C99 规范中新增的.
关于…和__VA_ARGS__
- … 是在函数或宏的参数列表中使用,表示该函数或宏可以接受可变数量的参数。它用于声明函数或宏的参数,并将实际传递的参数列表与之匹配。
注意,... 它不能在宏的展开中使用。 - ##VA_ARGS 是在宏定义中使用的特殊标记,用于表示可变参数的展开。它用于展开可变参数,并将展开后的参数列表与其前面的内容连接起来。## 是连接符,用于在没有额外参数时确保宏定义仍然有效。
__VA_ARGS__有两个不足点:
1.仅仅只支持字符串常量,不支持可变参数
#define LOGFUNC(...) (printf(__VA_ARGS__))
2.仅仅只支持可变参数,不支持字符串常量
#define LOGSTRINGS(fm, ...) printf(fm,__VA_ARGS__)
而上述情况可以使用##__VA_ARGS__,使用实例参考log4cxx.
如果可变参数被忽略或为空,## 操作将使预处理器(preprocessor)去除掉它前面的那个逗号.
如果你在宏调用时,确实提供了一些可变参数,GNU CPP 也会工作正常,它会把这些可变参数放到逗号的后面。
#include <time.h> #include <sys/times.h> #include <type_traits> #include <stdio.h> #include <stdint.h> #include <iostream> #define LOGFUNC(...) (printf(__VA_ARGS__)) #define LOGSTRINGS(fm, ...) printf(fm,##__VA_ARGS__) int main() { LOGSTRINGS("2"); LOGSTRINGS("%d,%s\n", 1, "this"); return 0; }
// 在宏定义中,fmt是一个占位符,用于表示格式字符串。fmt可以是一个字符串字面量,也可以是一个参数。
#define RTE_FMT_HEAD(fmt, ...) fmt // 只取第一个参数 fmt,后面的 ... 可变参数不会用到。
#define MY_MACRO(...) RTE_FMT_HEAD(__VA_ARGS__ ,)
#define MY_MACRO2(...) RTE_FMT_HEAD(__VA_ARGS__)
// 假设调用
//RTE_FMT_HEAD("abc", 123, 456)
// 展开后就是 "abc"
// MY_MACRO中__VA_ARGS__后面的,号主要用于宏参数分隔和兼容复杂宏展开场景,C 预处理器允许宏参数为空,不会报错。
如下例:
#define jiuyuanyiyao(name, type, qual) struct name{qual type f;} #define jiuyuan(name, type) jiuyuanyiyao(name, struct type,) jiuyuan(tst, int);
参考:
浙公网安备 33010602011771号