C语言可变参数

可变参数

c语言中实现可变参数列表

我们c语言中实现一个函数时我们会根据需要为它设计参数,当我们调用函数时必须给他对应的参数,不然就会出错。那我们如果参数个数不能确定,又必须要实现这个函数该怎么办呢?

如题:

实现一个函数求一组数(个数不定)的平均数
传参数,第一个参数为数的个数,后面每个为每个数的值
例如:average(3,1,2,6) 输出3。

那这就要依靠可变参数来实现了

 

语法格式

刚才求平均数的功能可以这样实现

#include <stdio.h>
#include <stdarg.h>

int average(int n,...)
{
    va_list argc;
    int i = 0;
    int sum = 0;
    va_start(argc,n);
    for(i = 0; i<n; i++)
    {
        sum += va_arg(argc,int);

    }
    va_end(argc);
    return sum/n;
}
int main()
{
    int ret = average(3,1,2,6);
    printf("%d\n",ret);
    return 0;
}

这样就可以实现刚才的功能了,但是大家可能看不懂,接下来先让大家明白意思再做详细解析

  • int average(int n,…)     要注意后面的三个点不是省略号,是英文的句号。
  • va_list  ——获取不确定个数的参数
  • va_start( ) ——指针指向可变参数第一个
  • va_arg( ) ——通过地址寻找每个可变参数
  • va_end( ) ——指针作废防止崩溃

我们现在只是明白了他的意思,现在我们通过原码来深度理解。
 
 

通过原码深度理解

va_list

这里写图片描述
可见其实va_list 相当于 char * 就是一个字符指针
 
 

va_start(argc,n)

这里写图片描述
他的作用就是取到 n 的地址并将 n 的大小取整后加上
我们知道函数在栈中开辟空间站由高地址向低地址使用
就是将arg指向了第一个可变参数的地址。
 
 

va_arg(argc,int);

这里写图片描述
通过地址取到第一个可变参,并将指针指向下一个可变参数
 
 

va_end(argc);

由上两幅图最后一行可知
就是将argc指针的值改为0即空指针
因为功能已实现完将argc改为空,防止非法访问程序崩溃

帮助理解我门将开始的代码用原码表达的意思来替换

#include <stdio.h>
#include <stdarg.h>

int average(int n,...)
{
    char* argc;                         //va_list argc;
    int i = 0;
    int sum = 0;
    argc = (char*)&n + 4;              //va_start(argc,n);
    for(i = 0; i<n; i++)
    {
        sum += (*(int*)((argc +=4)-4));  
                                       //sum += va_arg(argc,int);

    }
    argc = NULL;                      //va_end(argc);
    return sum/n;
}
int main()
{
    int ret = average(3,11,22,66);
    printf("%d\n",ret);
    return 0;
}

值得一提的是
(*(int*)((argc +=4)-4))
argc+=4将指针指向下一个可变参数
后面-4将值依然停留在当前可变参数地址
然后强转(int*)再解引用拿到第一个可变参数。

这短短一行完成三个功能,可见原码的高效。

希望大家基本了解了可变参数的基本用法和它的强大,
学会了它我们就可以模拟实现printf函数了!下一篇博客就讲解模拟它的实现。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值