c语言之可变参数函数

时间:2021-02-13 01:33:40

stdarg.h



stdarg.h是C标准函数库的头文件,主要目的是为让函数能够接收不定参数。当需要定义可变参数函数时,需要包含该头文件。




先从一个例子说起,这个例子想法来自<<head first c>>

#include <stdio.h>
#include <stdarg.h>

enum drink{apple = 3,banana = 4,orange = 5,other = 6};


int count(int n,...)
{
int total = 0;

va_list ap;
va_start(ap,n);

for (int i = 0; i < n; ++i) {
total += (int) va_arg(ap, enum drink);
}
va_end(ap);
return total;
}

int main()
{
printf("cost %d\n",count(3,apple,orange,other));
printf("cost %d\n",count(5,apple,apple,banana,other,orange));
}


该例子定义了一个饮料的类型,并设定好了饮料的价钱。

之后又定义了一个函数count来统计价格,第一个参数表示购买的个数,之后为购买的品种(可变),最后得到花费的总价钱。

//不定参数函数至少有一个命名的参数


输出:


cost 14

cost 21

Program ended with exit code: 0





现在说一下原理:

既然函数至少有一个命名的参数,那么就有了一个基准,就可以定义指针根据该基准变量的地址定位到后续参数的起始地址。

如果再知道后续参数的类型,那么根据参数类型的长度,可以通过指针取得参数的值。




再介绍一下那4个宏的用途:


va_list  : 定义上述的那个指针

va_start  :定位后续变量的地址。由于至少有一个可变参数(可以有多个),根据定位最后一个已知参数来知道后续参数的起始地址。

va_arg :  根据后续参数的类型,通过指针将数据取出。

va_end :    进行一些结束工作




最后回过来解释一下最前面的例子:

先定义了一个指针 va_list  ap;

通过 va_start函数 将指针ap 与已知参数n联系起来,定位到后续参数的起始地址。

定位好之后后通过va_arg函数。利用指针ap和参数类型来获得数据,由于该例子第一个参数是个数,知道for循环要进行求和的次数。

最后结束va_end。





附:

可变参数学习笔记