可变参数列表

   C语言中的可变参数是一个比较有趣的话题。还记得刚学习C语言函数时编写的数学函数(如最简单的求和、求平均值等)只能接收固定数量的参数进行计算,如果想要做出一个可以接收任意数量参数的数学函数只能依赖于数组,而且如果是使用数组进行传递势必要在main函数里对数组进行初始化,使用起来非常麻烦,而我们的可变参数就可以很好的解决这个问题。

   先来看一个小程序:

使用可变参数实现一个函数,可以求任意个参数的平均值:

#include<stdio.h>
#include<stdarg.h>
#include<stdlib.h>
int average(int n, ...)
{
va_list arg;
int sum = 0;
va_start(arg, n);
for (int i = 0; i < n; i++)
{
sum += va_arg(arg, int);
}
return sum / n;
va_end(arg);
}
int main()
{
int a = 2, b = 4, c = 6, ave1 = 0, ave2 = 0;
ave1 = average(2, a, b);
ave2 = average(3, a, b, c);
printf("%d %d\n", ave1, ave2);
system("pause");
return 0;
}


   上面的小程序很好的解决了一个函数接收任意数量参数的问题,但是在程序中出现了一些之前没见过的代码,下面我们对这些代码进行分析。

一、int average(int n, ...)、

    ave1 = average(2, a, b)、

    ave2 = average(3, a, b, c)、

    :定义函数时在形参处接收了一个n,这个n代表在本次调用中想要传递的参数个       数,在上面的这个程序中它主要起到了

      1)限制加法循环次数

      2)为va_start()提供了首地址(这里涉及到了栈帧的相关知识)

      的作用。

二、va_list arg:声明了一个va_list类型的变量arg,用于访问参数列表的未确定部     分。

三、va_start():arg变量使用va_start进行初始化,其第一个参数是va_list的变     量名,第二个参数是省略号前最后一个有名字的参数。初始化过程中把arg变量设     置为指向可变参数部分的第一个参数。

四、va_arg():为了访问参数,需要使用va_arg,这是一个接收两个参数的宏,参     数分别为va_list类型变量和参数列表中下一个参数的类型。使用va_arg会同时进     行两步操作,返回这个参数的值和使va_arg指向下一个参数。

五、在访问完毕最后一个可变参数后要使用va_end来消除变量arg。

   其实可变参数列表就是基于栈帧原理上实现的一系列宏定义,如果了解栈帧的话并不难理解这些操作是如何实现的。不过由于栈帧的内容比较庞大,在这里引出显得喧宾夺主,我会在以后的博客中专门讲述栈帧的原理,现在只给出上述几个宏的源代码供大家参考,对栈帧有了解的朋友可以参照它们进一步了解可变参数列表是如何实现的。

#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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值