今天在学习中,发现了函数的参数还可以是三个点的,让我有点奇怪。所以就去在网上查了一下,这个知识点称为“可变参数”。以下就是我对于可变参数的理解:
知识储备:
首先我们先了解一个知识点:在《STL源码剖析》这本书中,空间配置器那一章节中二级空间配置,需要每此申请空间个数为8的整数倍。以下就是其实现的方式。
下来,我们来看可变参数是如何实现的?
首先,我们来看一端代码:
#include
//#include
typedef char* va_list;
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define va_end(ap) ( ap = (va_list)0 )
int Avg(int n, ...) //可变参数的理解
{
int i;
int sum = 0;
va_list v1;
va_start(v1, n); //(v1 = (va_list)&n + _INTSIZEOF(n))
for (i = 0; i < n; i++)
{
//(*(int *)((v1 += _INTSIZEOF(int)) - _INTSIZEOF(int)))
sum += va_arg(v1, int);
}
va_end(v1); //v1 = (va_list)0;
return sum / n;
}
int main()
{
int avg = 0;
avg = Avg(3, 10, 20, 30);
printf("%d", avg);
return 0;
}
实现原理:
实现说明:
( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
此步骤含义同上面的知识储备
(v1 = (va_list)&n + _INTSIZEOF(n))
此步骤含义是将创建好的指针v1指向可变参数列表的第一个数据。
(*(int *)((v1 += _INTSIZEOF(int)) - _INTSIZEOF(int)))
此步骤含义是将创建好的指针向后移动,再减去sizeof(char)*4的偏移量,通过强转(int*)来取得参数的第一个值,循环移动,直至取至最后一个参数。
v1 = (va_list)0;
此步骤含义是将创建的指针v1赋值NULL(0);