可变参数解析

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中指定了错误类型,后果将不可预测。