什么是可变参数?
通常情况下,我们使用一个函数时总是需要知道这个函数需要传进去多少个参数,我们自己在写一个函数的时候也会先想好函数结构——参数个数和返回值。但是我们在使用printf() 函数的时候,我们发现我们想传多少个函数就能传多少个函数进去,从来没想过printf函数可以接受多少个参数。而事实是printf可以接受任意多个参数,因为printf函数使用了可变参数列表写的。
那么什么是C语言中的可变参数列表呢?通过函数实现为可变参数的形式,可以使得函数可以使函数接受1个或1个以上的任意多个参数(不固定的)。
先来看一个例子:
//实现一个函数可以求任意个参数的平均值。
int argv(int n, ...)
{
va_list arg;
int i = 0;
int sum = 0;
va_start(arg, n);
for (i = 0; i < n; i++)
{
sum += va_arg(arg, int);
}
return sum / n;
va_end(arg);
}
int main()
{
int arg1 = argv(6, 1, 2, 3, 4,5,6);//第一个参数代表要求值的个数
printf("argv1=%d\n", arg1);
system("pause");
return 0;
}
参数解析
- 首先我们需要声明一个va_list型的变量arg,它用于访问参数列表中未确定的部分。
- 然后我们需要调用va_start来对arg初始化。它的第一个参数是va_list里定义的变量名,第二个参数是省略号前最后一个有名字的参数。初始化过程就是把arg变量设置为指向可变参数部分的第一个参数。
- 为了访问参数,需要使用va_arg,这个宏接受两个参数——va_list变量和参数列表中下一个参数的类型,上述例子里所有的可变参数都是整型。va_arg返回这个参数的值并使va_arg指向下一个可变参数。
- 当访问完所有可变参数之后,我们需要带调用va_end();将指针置空。
所以简单的来说,这四个参数含义如下:
va_list arg;//定义一个指针arg
va_start(arg, n);//让指针指向n
va_arg(arg,int);//让指针指向下一个元素,int为指向的元素类型
va_end(arg);//将指针置空
可变参数的限制
- 可变参数必须从头到尾逐个。如果你访问了几个可变参数之后想半途终止,这是可以的;但是,如果一开始就想访问参数列表中间的参数,是不行的。
- 参数列表中至少有一个命名参数。如果一个命名参数都没有,就不能使用va_start。
- 这些宏无法直接判断实际存在参数的数量。
- 这些宏也无法直接判断实际存在参数的类型。
- 如果在va_arg中指定了错误的类型,那么结果是无法预测的。