可变参数函数
可变参数函数顾名思义是参数可变的函数,参数可变是指参数的数量可变。前面章节使用过的可变参数函数,最经典的就是printf()函数与scanf()函数,它们可以根据用户的需要传入数量不等的参数。
除了库函数,C语言还允许用户自定义可变参数函数。定义可变参数函数时,第一个参数是固定强制的int类型,用于指定参数个数;定义好固定参数之后,再定义可选参数,可选参数使用三个点号(…)表示。
定义可变参数需要包含stdarg.h标准库文件,该标准库定义了实现可变参数函数需要的变量和宏。下面分步骤介绍C语言可变参数函数的定义。
(1) 在程序顶部包含stdarg.h标准库文件。
(2) 定义函数,指定固定的参数,最后一个参数用省略号表示。
(3) 在函数中定义一个va_list类型变量,该类型在stdarg.h中定义。
(4) 使用int类型参数(参数个数)和宏va_start初始化va_list变量,使其成为一个参数列表。宏va_start在stdarg.h标准库文件中定义。
(5) 使用宏va_arg和va_list变量访问参数列表中的每一项。
(6) 使用宏va_end清理赋予va_list变量的内存。
根据上述步骤,定义一个可变参数函数,具体如例1所示。
例1 var.c
1 #include <stdio.h>
2 #include <stdarg.h>
3 void func(int n, ...) //定义可变参函数
4 {
5 va_list valist; //定义va_list类型变量
6 va_start(valist, n); //宏va_start和参数n初始化valist为参数列表
7 for (int i = 0; i < n; i++) //通过for循环访问参数列表
8 printf("%d ", va_arg(valist, int)); //访问到每一个参数后将其输出
9 va_end(valist); //使用宏va_end清理valist的内存
10 }
11 int main()
12 {
13 func(1,1); //调用func()函数,传入2个参数
14 printf("\n");
15 func(2, 6, 9); //调用func()函数,传入3个参数
16 printf("\n");
17 func(3, 100, 24, 88); //调用func()函数,传入4个参数
18 printf("\n");
19 return 0;
20 }
例1运行结果如图1所示。
图1 例1运行结果
在例1中,第3~10行代码定义了可变参数函数func(),在func()中,参数n是固定的参数,用于指定后面可变参数的个数。第13~18行代码分别传入不同个数的参数来调用func()函数,第13代码调用func()函数,传入2个参数,第一个参数1表示有一个可变参数,第二个参数1为实际参数;第15行代码调用func()函数,传入3个参数,2表示有两个可变参数,6和9是实际可变参数;第17行代码有4个参数,第一个参数3表示有三个可变参数,100、24、88是实际可变参数。由图1可知,三次函数调用均成功。
需要注意的是,调用可变参数函数时,传入的参数会存储在可变参数列表中,函数从参数列表中获取每一个参数参与运算,该参数列表实质上就是一个动态数组,在使用完毕后,需要使用宏va_end进行释放,否则会造成内存泄露。