今天在学习中,发现了函数的参数还可以是三个点的,让我有点奇怪。所以就去在网上查了一下,这个知识点称为“可变参数”。以下就是我对于可变参数的理解:
知识储备:
首先我们先了解一个知识点:在《STL源码剖析》这本书中,空间配置器那一章节中二级空间配置,需要每此申请空间个数为8的整数倍。以下就是其实现的方式。
下来,我们来看可变参数是如何实现的?
首先,我们来看一端代码:
#include<stdio.h> //#include<stdarg.h> 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);