可变参数列表
可变参数列表
也许你想有一个函数,可以接受任意数量的值,然后返回平均值。你不知道会有多少个参数传递给函数。你可以通过接受一个指向数组的指针来制作这个函数。另一种方法是编写一个可以接受任意数量参数的函数。所以你可以写 avg(4, 12.2, 23.3, 33.3, 12.1);或者你可以写 avg(2, 2.3, 34.4);这种方法的优点是,如果你想改变参数的数量,更容易修改代码。事实上,一些库函数可以接受可变数量的参数(例如 printf——我敢打赌你一直在想它是怎么工作的!)。
当一个函数声明为具有不确定数量的参数时,你应该在最后一个参数的位置放置一个省略号(看起来像 '...'),所以,int a_function ( int x, ... ); 会告诉编译器这个函数应该接受程序员使用的任意数量的参数,只要它至少等于一个,第一个参数 x。
我们需要使用 stdarg.h 头文件中的一些宏(这些宏与函数非常相似,你可以将它们当作函数来处理)来提取存储在可变参数列表中的值——va_start 用于初始化列表,va_arg 用于返回列表中的下一个参数,va_end 用于清理可变参数列表。
要使用这些函数,我们需要一个能够存储可变长度参数列表的变量——这个变量将是 va_list 类型。va_list 与其他类型类似。例如,以下代码声明了一个可以用来存储可变数量参数的列表。
va_start 是一个接受两个参数的宏,第一个参数是 va_list,第二个参数是省略号("...")直接前面的变量的名称。因此,在函数 a_function 中,要使用 va_start 初始化 a_list,你应该写成 va_start(a_list, x);
int a_function ( int x, ... )
{
va_list a_list;
va_start( a_list, x );
}va_arg 函数接受一个 va_list 和一个变量类型,并以该变量类型的形式返回列表中的下一个参数。然后它会移动到列表中的下一个参数。例如,va_arg(a_list, double)将返回下一个参数(如果存在),并以 double 类型的形式返回。下次调用时,它将返回上一个返回的数字之后的参数(如果存在)。请注意,您需要知道每个参数的类型——这就是为什么 printf 需要一个格式字符串的原因!完成后,使用 va_end 来清理列表:va_end(a_list);
为了展示每个部分的工作原理,以一个示例函数为例:
#include <stdarg.h>
#include <stdio.h>
/* 这个函数将取要取平均值的数值,然后取所有要取平均值的数值 */
double average ( int num, ... )
{
va_list arguments;
double sum = 0;
/* 初始化参数以存储num之后的所有值 */
va_start ( arguments, num );
/* 对所有输入求和;我们仍然依赖函数调用者来告诉我们有多少 */
for ( int x = 0; x < num; x++ )
{
sum += va_arg ( arguments, double );
}
va_end ( arguments ); // 清理列表
return sum / num;
}
int main()
{
/* 这将计算12.2、22.3和4.5的平均值(3表示要平均的值的数量)。 */
printf( "%f\n", average ( 3, 12.2, 22.3, 4.5 ) );
/* 这将计算3.3, 2.2, 1.1, 5.5, 3.3的平均值(5表示要平均的值的数量)。 */
printf( "%f\n", average ( 5, 3.3, 2.2, 1.1, 5.5, 3.3 ) );
}并非总是使用可变参数列表是一个好主意;存在假设一个值是某种类型,而实际上它是另一种类型的可能性,例如假设空指针是一个整数。因此,可变参数列表应该谨慎使用。
