C语言中的可变参数是通过函数来实现可变参数的形式,可以使得函 数可以接受1个以上的任意多个参数(不固定)
在实现可变参数的过程中,主要有以下四个要点:
va_list arg : char * arg,定义一个
char * 类型的指针变量。
va_start (arg,n): arg = (char *)&n + ((sizeof(n)+sizeof(int)-1) & ~(sizeof(int)-1)). 获得第一个未知参数的地址。
其中
((sizeof(n)+sizeof(int)-1) & ~(sizeof(int)-1))的作用是保证取的都是整型空间大小的幂次方,能够保证取到未知数的正确的位置。在这篇文章中对
((sizeof(n)+sizeof(int)-1) & ~(sizeof(int)-1))有很详细的讲解。
va_arg(arg,int) :(*(int *)((arg += ((sizeof(n)+sizeof(int)-1) & ~(sizeof(int)-1))) - ((sizeof(n)+sizeof(int)-1) & ~(sizeof(int)-1)))); 作用是在对求和的同时,能够实现arg指向的地址的自增。
va_end(arg) : ( ap = (va_list)0 ),在使用完指针之后,让其指向为空。
以下是用代码实现的例子:
//源码分析
int average(int n, ...)
{
//typedef char * va_list 将char * 类型重定义为va_list
//va_list arg;
char * arg; //将arg定义为char *类型的变量,使得它指向的是一个地址
int i = 0;
int sum = 0;
//#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) ) 使用宏替换
//va_start(arg, n);
//#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
//_INTSIZEOF(n)的作用是保证取的都是整型空间大小的幂次方,能够保证取到未知数的正确的位置
arg = (char *)&n + ((sizeof(n)+sizeof(int)-1) & ~(sizeof(int)-1));
for (i = 0; i < n; i++)
{
//#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
//sum += va_arg(arg, int);
sum += (*(int *)((arg += ((sizeof(n)+sizeof(int)-1) & ~(sizeof(int)-1))) - ((sizeof(n)+sizeof(int)-1) & ~(sizeof(int)-1))));
//作用是在对求和的同时,能够实现arg指向的地址的自增。
}
return sum / n;
//#define va_end(ap) ( ap = (va_list)0 )
//va_end(arg);
arg = (char *)0; //在使用完arg之后使其指向为空,保证安全性。
}
int main()
{
int a = 10;
int b = 20;
int c = 30;
int ret = average(3, a, b, c);
printf("%d\n", ret);
return 0;
}