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; }