可变参数列表源码的解析

C语言中的可变参数是一个比较有意思的实现,一旦将某个函数组装成参数可变的函数,它可以接受任意多个参数。从定义中我们不难体会到常用的printf 和 scanf等函数是这类函数,感谢我们的前辈,他们已实现的函数给我们带来了极大的便利。下面谈谈我对可变参数的理解,首先写一个参数可变的函数(实现求几个数的平均值)。
#include<stdio.h>
#include<windows.h>
#include<stdarg.h>
int average(int nums,...)
{
int sum = 0;
va_list arg;
va_start(arg,nums);
while(nums--)
{
sum += va_arg(arg,int);
}
return sum/nums;
va_end(NULL);
}
int main()
{
printf("ave1 = %d\n",average(2,10,20));
printf("ave2 = %d\n",average(2,10,20,30));
system("pause");
return 0;
}
读懂和深度理解这个程序的关键是对va_list,va_tast,va_arg,va_end这四个新朋友的功能理解,我们欢迎他们,下面我给大家介绍这四个朋友:
va_list arg:这个很好理解,它相当于 char *arg ,相信说到这里对这个不许过多解释。
va_tast(arg,nums):说直白点这里实现了一个初始化,它实现的功能是将 arg 指向未知的第一个参数; 这里对很多朋友可能有点误导,很可能会理解成此处 nums 处的对象是从左至右参数部分的第一个参数,这里并不是这样,这里的对象应该是在参数中从左至右离 ... 最近的那个参数。这句代码的汇编是 ap = (va_last)&v + _INTSIZEOF(v) ( ap 相当于此处的 arg , v 相当于此处的 nums ),_INTSIZEOF(v) 实现整形提升,即就是当 v 所代表的类型所占的字节是 1,2,3,4 时, _INTSIZEOF(v)的值为 4 ,当 v 所代表的类型所占的字节是 5,6,7,8 时, _
INTSIZEOF(v) 的值是 8 ,结合形参实例化的过程从这句汇编容易理解为什么 ap 指向的第一个是未知参数,至于为什么要进行整形提升此处不作解释,有能力的朋友评论做个解释,分享给大家,谢谢。
va_ arg(arg,int):此表达式是可变参数函数实现的核心,它即实现了取当前 arg 所指向的对象实体,又实现了将 arg 指向下一个参数的功能。这句代码的汇编是 *(t *)((ap += _INTSIZEOF(t)) - _INTsizeof(t)) ( t 相当于此处的 int ,代表相对应的参数的类型,一个函数中可以有 int char 等等),不难发现 ap += _INTSIZEOF(t) 实现了将 ap 指向下一个参数, (t*)((ap += _INTSIZEOF(t)) - _INTsizeof(t)) 实现了取当前 ap 所指向的那个值。这个操作真的真的是厉害炸了。
va_end(NULL):我觉得这里体现出了我们程序员的职业性,就是最后将 ap 赋成NULL。 
最后感谢各位的阅读,我是一个初学者,错误难免,有问题或者解释不明的请朋友们评论交流。谢谢各位

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值