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。
附:
可变参数学习笔记