C语言的可变参数函数
目录
- C语言 可变参数
- 参数
- 小例子
- 实现相关的宏
- 完整例子
- 实现原理
C语言 可变参数
C 语言允许定义参数数量可变的函数,这称为可变参数函数。这种函数需要
- 固定数量的强制参数(mandatory argument)
- 数量可变的可选参数(optional argument)。
C 语言中最常用的可变参数函数例子是
printf()
和scanf()
。这两个函数都有一个强制参数,即格式化字符串。格式化字符串中的转换修饰符决定了可选参数的数量和类型。可变参数的个数(百分号的个数)、可变参数的类型(%s、%d等)
参数
可变参数函数的参数定义:
每一个强制参数来说,函数头部都会显示一个适当的参数,像普通函数声明一样。
参数列表的格式是强制性参数在前,后面跟着用三个小数点 "..."
表示这个位置可以有多个参数,参数的类型和个数不是固定的。
小例子
简明扼要的小例子:
int func(int, ... ) //int类型参数代表了可变参数个数
{
//实现
}
int main()
{
func(2, 2, 3);
func(3, 2, 3, 4);
}
实现相关的宏
可变参数函数的实现:
-
头文件
-
va_list
变量类型用来保存可变参数"..."
位置等信息的参数列表。这种类型的对象也称为参数指针(argument pointer),它包含了栈中至少一个参数的位置。可以使用这个参数指针从一个可选参数移动到下一个可选参数。可以用 4 个宏来处理该参数指针 -
宏
va_start
是初始化va_list
参数表void va_start(va_list argptr,lastparam); //用第一个可选参数的位置来初始化 argptr 参数指针 //该宏的第二个参数必须是该函数最后一个有名称参数的名称 //必须先调用该宏,即初始化操作
-
宏
va_arg
是从va_list
参数表里面获取一个参数,并且指向下一个参数type va_arg(va_list argptr,type); //宏的第二个参数是刚刚被读入的参数的类型
-
宏
va_end
释放va_start
初始化参数表占用的资源,当不需要使用该参数指针时必须调用该宏。void va_end(va_list argptr);
-
宏
va_copy
使用当前的src
值来初始化参数指针dest
void va_copy(va_list dest, va_list src);
完整例子
一个完整使用的例子:
double add(int n,...)
{
int i=0;
double sum=0;
va_list argptr;
va_start(argptr,n); //初始化,n为可变参数个数
for(int i=0;i
实现原理
可变参数的传递从右往左压入栈中,栈是向低地址拓展的,取参数时再从低到高(从左往右)。
64 位机器用 8 字节对齐, 32 位 4 位对齐
具体这一块相关的信息可以看操作系统或者编译原理中涉及用户栈和参数调用的过程。