可变参数解析
Q: 什么是可变参数列表?
A: 通过将函数实现为可变参数形式,可以使得函数可以接受一个以上的任意多个参数(不是固定的)
首先我们看一个例子
#include <stdio.h>
#include <stdarg.h>
int Avg(int n, ...)
{
va_list arg;
int i = 0;
int sum = 0;
va_start(arg,n);
for (i=0;i<n;i++)
{
sum += va_arg(arg,int);
}
return sum/n;
va_end(arg);
}
int main()
{
int ret = Avg(3,1,2,3);
printf("Avg=%d\n",ret);
return 0;
}
1、首先,声明一个va_list 类型的变量arg,用来访问传进来的未确定参数。
va_list arg ; // 等同于char* arg;
2、然后调用va_start来初始化,把arg设置为指向可变canshu参数部分的第一个参数。当然,第一个参数是va_list的变量名,第二个参数是省略号前最后一个有名字的参数。
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
#define _crt_va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
3、我们用va_arg访问参数,这个宏接收两个参数,va_list变量和列表中下一个参数的类型,以下是宏定义中va_arg的定义
#define _crt_va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
4、当我们访问完最后一个参数时,我们调用va_end,以下就是在宏定义中的定义,其实就是让指针为NULL
#define _crt_va_end(ap) ( ap = (va_list)0 )
可变参数限制
1、可变参数必须从头到尾逐个访问,如果在访问几个可变参数之后想半途而废,这个是可以的,但是,一开始你就想从某个参数开始访问是不行的。
2、参数列表中至少有一个命名参数,如果连一个命名参数都没有,就无法使用va_start。
3、这些宏是无法直接判断实际存在参数的数量。
4、这些宏是无法判断每个参数的类型。
5、如果在va_agr中指定了错误类型,后果将不可预测。