介绍
C语言中,printf()
和scanf()
函数就是典型的变参函数,其优点是灵活处理参数。
想要创建变参函数需引入头文件stdarg.h
,它有一些宏:
1 2 3 4 5 6 7 8 9 10 11
| va_list 指向整个可变参数列表的指针 原型:typedef char* va_list;
va_start 指向可变参数列表前的参数(...前的参数) 原型:void va_start(va_list ap, paramN);
va_arg 可变参数列表 原型:typedef va_arg(va_list ap, type)
va_end 结束对可变参数列表的访问,并释放资源 原型:void va_end(va_list ap);
|
使用例
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
| #include <stdio.h> #include <stdarg.h>
void function(int argument, ...) { va_list ap;
va_start(ap, argument);
int output = va_arg(ap, int);
printf("可变参数:%d\n", output);
va_end(ap); }
int main() { function(1, 109); }
|
输出:
函数起了作用,但是如果我们需要接受多个参数,应该如何获取呢?
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 34 35 36
| #include <stdio.h> #include <stdarg.h>
void function(int argument, ...) { va_list ap;
va_start(ap, argument);
int arguments_list[4];
for(int i = 0; i < 4; i++) { arguments_list[i] = va_arg(ap, int); }
va_end(ap);
for (int i = 0; i < 4; i++) { printf("可变参数%d:%d\n", i + 1, arguments_list[i]); }
}
int main() { function(1, 10, 12, 2, 111); }
|
扩展:va_start
的第二个参数的工作原理
va_start
的第二个参数用于定位可变参数列表的起始位置,具体而言,它指向函数参数列表中最后一个固定参数(即省略号前的参数),通过该参数的地址计算出第一个可变参数在内存中的位置。
C函数的参数按从右至左顺序入栈(栈底高地址,栈顶低地址)
va_start
的第二个参数作为基准点,其地址加上自身大小后,即指向第一个可变参数的起始地址。
所以...
前至少要有一个固定参数用于寻址。