#include
//...表示不定参数列表,__VA_ARGS__是宏,代表不定参数列表部分
// __FILE__ 宏 代表 : 文件名
//__LINE__ 宏 代表 : 行号
//__VA_ARGS__ 用于在宏替换部分中,表示可变参数列表;
//当可变参数的个数为0时,##起到把前面多余的","去掉的作用,否则会编译出错
//要注意空格的使用
#define LOG(format, ...) printf("[%s:%d]" format,__FILE__,__LINE__,##__VA_ARGS__);
int main()
{
LOG("可变参数列表\n");
//最终展开的代码相当于printf("[%s:%d]" "可变参数列表\n",__FILE__,__LINE__)
//如果不加##,会报错
printf("%d ""nihao\n",6);//可以编译通过
return 0;
//上面的 [%s:%d] format 会自动拼接在一起 都是字符串
}
#include
#include
void print(int cnt, ...)
{
// 使用之前定义va_list 变量
va_list ap;
// void va_start(va_list ap,param);
va_start(ap, cnt); // 获取cnt参数之后的第一个参数的地址即第一个不定参地址
for (int i = 0; i < cnt; ++i)
{
// type va_arg(va_list ap,type);
int num = va_arg(ap, int); // 获取不定参
printf("param[%d]:%d\n", i, num);
}
// void va_end(va_list ap);
va_end(ap); // 使用完将ap指针置空
}
//在print函数的实现中,我们首先通过va_start初始化ap变量,然后使用一个循环来遍历cnt个可变参数。
//在循环体中,我们使用va_arg逐个获取可变参数,并使用printf函数打印每个参数的值。最后,我们使用va_end清理ap变量。
int main()
{
print(3,1,2,3);
return 0;
}
//运行结果
//param[0]:1
//param[1]:2
//param[2]:3
va_list ap
va_list ap:va_list是一个类型,用于存储可变参数的列表。在函数内部,我们定义了一个ap变量,它将用于访问可变参数列表中的实际参数。
va_start()函数 语法
void va_start(va_list ap,param);
//va_start(ap, cnt):va_start宏用于初始化ap变量,用于访问可变参数。
//它接受两个参数,第一个参数是一个va_list变量,
//第二个参数是可变参数列表的前一个参数(在本例中是cnt)。
//这个宏的作用是设置ap为指向第一个不定参数的指针。
va_arg()函数用于调用可变参数列表
type va_arg(va_list ap,type);
//va_arg(ap, int):va_arg宏用于访问可变参数列表中的实际参数。
//它接受两个参数,第一个参数是一个va_list变量,
//第二个参数是希望返回的参数类型。在本例中,我们使用int作为参数类型。
//这个宏的作用是返回当前可变参数列表中的下一个实际参数,
//并将指针ap移到下一个参数位置。
va_end()函数用于停止使用可变参数。
void va_end(va_list ap);
//va_end(ap):va_end宏用于结束对可变参数的访问。
//它接受一个参数,即一个va_list变量。
//这个宏的作用是清理va_list变量在访问参数列表时所做的任何操作,
//并将ap指针置空。
以printf(const char* format,…)
为例
使用不定参模拟实现printf
int vasprintf(char **strp, const char *fmt, va_list ap);
vasprintf 是一个 C 库函数,它可以通过可变参数创建一个格式化的字符串,并将其存储在动态分配的内存中。它的使用方法与 printf 类似,但它不会将结果打印到标准输出流中,而是将其存储在一个指向字符数组的指针中 成功返回字符串长度,失败返回-1
void MyPrint(const char *fmt, ...)
{
va_list ap;
va_start(ap,fmt);
char* res;
int ret=vasprintf(&res,fmt,ap);
if(ret !=-1)
{
printf(res);
free(res);
}
va_end(ap);
}
需要借助C++11内的万能引用与完美转发及可变参数模版包
#include
#include
#include
#include
//特化
void CgagaPrint()
{
std::cout<<std::endl;
}
template<class T,class ...Args>
void CgagaPrint(const T& v,Args&& ...args)
{
std::cout<<v;
if((sizeof ...(args))>0)
{
//完美转发
CgagaPrint(std::forward<Args>(args)...);
}
else
{
CgagaPrint();
}
}
int main()
{
CgagaPrint("nihao",6,5,4);
}