理解可变参数的原理

今天在学习中,发现了函数的参数还可以是三个点的,让我有点奇怪。所以就去在网上查了一下,这个知识点称为“可变参数”。以下就是我对于可变参数的理解:

知识储备:

首先我们先了解一个知识点:在《STL源码剖析》这本书中,空间配置器那一章节中二级空间配置,需要每此申请空间个数为8的整数倍。以下就是其实现的方式。image

 下来,我们来看可变参数是如何实现的?

首先,我们来看一端代码:

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

实现原理:

image

实现说明:

( (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);

 

原文地址:https://www.cnblogs.com/single-dont/p/11253451.html