在函数原型中,列出了函数期望接受的参数,但原型只能显示固定数目的参数。让一个函数在不同的时候接受不同数目的参数是不是可以呢?答案是肯定的,但存在一些限制。
考虑一个计算一系列值的平均值的函数。如果这些值存储于数组中,这个任务就太简单了,所以为了让问题变得更有趣一些,我们假定它们并不存储于数组中。先来看一个计较差的,也是不太稳定的一个解决方案:
1 //计算指定数目的值的平均值(差的方案) 2 float average(int n_value,int v1,int v2,int v3,int v4,int v5) 3 { 4 float sum=v1; 5 if(n_values>=2) 6 sum+=v2; 7 if(n_values>=3) 8 sum+=v3; 9 if(n_values>=4) 10 sum+=v4; 11 if(n_values>=5) 12 sum+=v5; 13 return sum/n_values; 14 }
这个函数存在几个问题:首先,它不对参数的数量进行测试,无法检测参数过多的这种情况。不过这个问题容易解决,简单加上测试就是了。其次,函数无法处理超过5个的值。要解决这个问题,你只有在已经很臃肿的代码中再增加一些类似的代码。另外还存在一个更为严重的问题:就是实参数与形参的对应不一定准确。
stdarg宏
可变参数列表是通过宏来实现的,这些宏定义stdarg.h头文件,它是标准库的一部分。这个头文件声明了一个类型va_list和
三个宏——va_start、va_arg、va_end。我们可以声明一个类型为va_list的变量,与这几个宏配合使用,访问参数的值。
下面的程序使用三个宏正确的完成计算指定数目的值的平均值的任务。
1 //指定数量的值的平均值 2 #include<stdarg.h> 3 float(int values,...) 4 { 5 va_list var_arg; 6 int count; 7 float sum=0; 8 9 var_start(var_arg,values);//准备访问可变参数 10 for(count=0;count<values;count+=1) //添加取自可变参数表的值 11 { 12 sum+=va_arg(var_arg,int); 13 } 14 var_end(var_arg); //完成处理可变参数 15 return sum/n_values; 16 }