在工作中经常碰到带有使用可变参数的函数
目前C提供的可变参数的申明为
void function(const char *format, ...);
这样就可以在function中使用可变参数
C提供了几个宏用于使用可变参数
va_list
va_start
va_arg
va_end
其中
va_list用于定义一个变量获取可变参数指针
va_start用于将va_list定义的指针进行初始化
va_arg用于获取对应指针的真实类型数据
va_end用于清空va_list定义的指针
// 下面给出一个可变参数的具体例子,这个函数可以计算任意多个int值的和
int sum(int number, ...)
{
va_list arg_ptr = NULL;
va_start(arg_ptr, number);
int sum = 0;
for(int i=0; i<number; i++)
{
sum += va_arg(arg_ptr, int);
}
va_end(arg_ptr);
return sum;
}
2 原理:
我们来看看这几个宏到底干了什么
typedef char * va_list; // 这个仅仅是个重定义而已。。。
// 获取v的地址
#define _ADDRESSOF(v) ( &(v) )
// n的整数字节的大小,必须是sizeof(int)的整数倍。如sizeof(n)为5的话,_INTSIZEOF(n)为8(假设为32位机器的话)
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
// 给v的地址加上v的大小
#define va_start(ap,v) ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
// 给ap自增t的大小,并且获取原有ap的地址的数据,强制转型为t类型
// 这个相当于 ( *(t *)ap )
// (ap += _INTSIZEOF(t))
// 这一个宏相当于完成两件事情
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
// 给ap置0
#define va_end(ap) ( ap = (va_list)0 )