可变参数列表解析

定义:什么叫可变参数列表呢,顾名思义,可变参数,就是函数可以接受的参数是可变的,可以接受1个以上任意多个参数。(至少是一个)

接下来先看一个列子:

#include <stdio.h>
#include <stdarg.h>
int average(int n,...)
{
    va_list arg;
    int i = 0;
    int sum = 0;
    va_start(arg, n);
    for(i=0; i<n; i++)
    {
    sum +=va_arg(arg, int);
    }
    return sum/n;
    va_end(arg);
}

int main()
{
    int a = 1;
    int b = 2;
    int c = 3;
    int avg1 = average(2, a, c);
    int avg2 = average(3, a, b, c);
    printf("%d\n", avg1);
    printf("%d\n", avg1);
    return 0;
}

上面的函数实现的是求任意个整数的平均值,因为传的参数不是固定的(但至少要传一个,且知道类型,原因稍后解释)

要想深入了解可变参数,首先我们必须对函数的栈帧结构有一定的了解,我们来看下面这张图这里写图片描述

这张图表示的是main函数调用myfun函数形成栈帧结构的过程,同理上面代码中的main调用average函数也会形成类似的栈帧结构,对函数栈帧有了解的都应该知道,函数参数实例化是从右到左的,(即如上图中a,b传过来a是后过来,即a在下面(低地址))而上面的可变参数,至少要传一个,这样我们就可以通过传过来n,来间接找到传过来的参数,不管传几个,我们都可以通过指向n的指针再加上对应的类型来找到相应的参数。例如:我们要通过a的地址找到b,就可以这样做,*p=&a,(p+1)(+1指的是加上指针所指类型的大小)再解引用就是b了。

接下来在解释上面代码中宏函数有什么作用:

va_list arg:这里arg的类型一定是 char * ,为什么是char * ,这很容易理解,因为char *指针加减1,就是增加或减少1,适用于找到各种类型的参数。
va_start(arg, n):这里先将n的地址赋给arg,再将arg加上n的大小,从而让指针指向不确定的部分。
va_arg(arg, int):这个宏函数的作用是通过类型提取指定参数,怎么做到的呢?上面我们已经将arg指向了不确定部分,即n的下一个参数(假设下面的参数分别是a, b, c….)a,要想提取a,我们可以先将指针指向的类型强转为a的类型,然后解引用就可就提取出a,arg再加上a的大小,然后再将指针指向的类型强转为b的类型,然后再解引用就可以提取出b,同理,可以提取出接下开的参数。
va_end(arg):作用就是将指针arg设置为NULL,这里不多做解释。

可变参数的限制

注意:

可变参数必须从头到尾逐个访问。如果你在访问了几个可变参数之后想半途终止,这是允许的,但是,如果你想一开始就访问参数列表中间的参数,那是不行的。

1.参数列表中至少有一个命名参数。如果连一个都没有,就无法使用va_start。
2.这些宏是无法直接判断实际存在参数的数量。
3.这些宏无法判断每个参数的类型。
1.如果va_arg中指定了错误的类型,那么其后果是不可预测的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值