一、可变长参数介绍
某些情况下为了完成一些功能,需要用到可变长参数的函数,例如我们最常用的printf和scanf函数:
1 2 |
scanf("%d %d", &a, &b); printf("%d %d\n", a, b); |
它们首先都是一个字符串打头,后面再跟上不定数量的参数,为我们的输出形式提供了多样性。
对于像这样的不定长参数的函数来说,它的声明形式为:
1 |
int func(int a, int b, ...); |
...
表示不定长度的参数,和函数形参的默认值一样,...
也只能放在函数的最后,否则函数无法判断出哪些才是不定参数。
二、变参使用
变参函数内部是通过栈来实现的,对于每一个参数来说,在调用时它们都会从右到左依次被压入栈中,而栈的性质是先进后出,所以在使用时会从左到右提取。
C语言中定义了一种类型va_list
来提取这些参数,va_list类型的定义如下:
1 2 |
// stdarg.h typedef va_list char* |
提取需要用到的API函数为va_start
和va_arg
,其用法如下:
1 2 3 4 5 6 7 8 9 10 |
void f(const char *arg, ...) { va_list args; //初始化args指向强制参数arg的下一个参数,即第一个不定参数的地址 va_start(args, arg); //获取当前参数内容并将args指向下一个参数,type表示当前的元素类型 va_arg(args, type); // ... 操作 va_end(args); //释放args } |
三、使用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
#include <stdio.h> #include <stdarg.h> /* * 求和 * @param argc 参数个数 * @param ... 可变参数列表 * @return 所有参数的和 */ int sum(int argc, ...) { int sum = 0, tmp; // 初始化参数 va_list argv; va_start(argv, argc); for (int i = 0; i < argc; i++) { // 循环获取每一个参数 tmp = va_arg(argv, int); printf("%d\n", tmp); sum += tmp; } // 销毁参数 va_end(argv); return sum; } int main() { printf("sum = %d\n", sum(3, 10, 20, 30)); printf("sum = %d\n", sum(4, 40, 39, 38, 37)); return 0; } |
运行结果:
1 2 3 4 5 6 7 8 9 10 |
$ ./debug/app 10 20 30 sum = 60 40 39 38 37 sum = 154 |
评论