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);

 

参考:

字符串化#、拼接字符##和可变参数宏(...和_ _VA_ARGS_ _)   

一起学习log4cxx    

C++委托模式

posted @ 2025-10-15 10:57  PKICA  阅读(29)  评论(0)    收藏  举报