stdarg宏
可变参数列表是通过stdarg.h头文件内的stdarg宏来实现的,stdarg.h头文件是标准库的一部分。在头文件中声明了一个va_list类型,还有三个宏--va_start、va_arg和va_end,在使用时需要先定义一个类型为va_list的变量,与这几个宏配合使用,访问参数值。
在函数内需要声明一个叫var_arg的变量,用于访问参数列表的未确定部分。这个变量是通过调用va_start来初始化的。其第一个参数是va_list变量的名字,第2个参数是省略号前最后一个有名字的参数,初始化过程会把var_arg变量设置为指向可变参数部分的第一个参数。
为了访问参数,需要使用va_arg,这个宏接受两个参数:va_list变量和参数列表中下一个参数的类型。在下面的程序中所有的可变参数都是整形。在有些函数中可能需要通过前面获得的数据来判断下一个参数的类型。va_arg返回这个参数的值,并使var_arg指向下一个可变参数。最后当访问完最后一个可变参数后,要调用va_end进行收尾。
可变参数的限制
可变参数必须从头到尾按照顺序逐个访问。允许在访问几个可变变量参数后中途停止。但是无法从一开始就直接访问参数列表中的参数。另外由于参数列表中的可变参数部分都没有原型,所以所有作为可变参数传递给函数的值都将执行缺省参数类型提升。
va_list 用于定义一个指向参数的指针,其实就是一个char* 的指针。
va_start(v1, num); 将v1指针指向可变参数的第一个参数。通过打印*v1可知,打印出来的是,1 ,正是第一个可变参数。
res = va_arg(v1, int); 这个函数返回v1指针所指的值,并使v1指针
移动sizeof(int) = 4, 个字节,使其指向下一个参数。以前一直以为当参数类型为char 时,应该写char, 但是今天实践了一下发现,当为char时系统会自动提升为int,当为float时自动提升为double, 字符串时为char * 。。。。…
va_end(v1); 最后一句,为了安全性,关闭v1指针,其实就是使v1为null。
#include<stdio.h>
#include<stdarg.h>
void fun(int num, ...)
{
int i;
int res = 0;
va_list v1; //v1实际是一个字符指针,从头文件里可以找到
va_start(v1, num); //使v1指向可变列表中第一个值,即num后的第一个参数
printf("*v = %d\n",*v1);
for(i = 0; i < num-1; i++) //num 减一是为了防止下标超限
{
res = va_arg(v1, int); //该函数返回v1指向的值,并是v1向下移动一个int的距离,使其指向下一个int
printf("res = %d, *v1 = %d\n",res, *v1);
}
va_end(v1); //关闭v1指针,使其指向null
}
int main(void)
{
fun(4,1,2,3,4);
return 0;
}