前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >举例分析可变参数函数实现的过程

举例分析可变参数函数实现的过程

作者头像
lexingsen
发布2022-02-24 15:23:29
5380
发布2022-02-24 15:23:29
举报
文章被收录于专栏:乐行僧的博客乐行僧的博客

求总和函数(可变参数形式)

代码语言:javascript
复制
int average(int n,...)
{
    int sum;
    va_list args;
    va_start(args,n);
    for(int i = 0;i<n;++i)
    {
        sum += va_arg(args,int);
    }
    va_end(args);
    return sum;
}
代码语言:javascript
复制
typedef char *  va_list   //为char* 别名为va_list

函数栈调用 对于C语言,其调用遵循_cdecl规则: 1.所有参数从右到左依次入栈。 2.这些参数由调用者清除,称为手动清除。 3.被调用函数不会要求调用者传递多少参数,调用者传递过多或者过少的参数,甚至完全不同的参数都不会产生编译阶段的错误。(简化的将就是调用参数的类型和数量不会产生编译阶段的错误)

以求和函数举例

代码语言:javascript
复制
int sum = sum(3,4,5,6);
这里写图片描述
这里写图片描述

三个宏宏定义

(1)va_start

代码语言:javascript
复制
#define va_start        _crt_va_start
#define _crt_va_start   va_start(ap,v)
#define va_start(ap,v)  (ap = (va_list)&v + _INTSIZEOF(v)) 
#define _INTSIZEOF(v) ((sizeof(v) + sizeof(int) - 1) & ~(sizeof(int)-1))

va_start宏的作用:

代码语言:javascript
复制
#define va_start(ap,v)  (ap = (va_list)&v + _INTSIZEOF(v)) 
ap = (char*)&v + (sizeof(v) + sizeof(int) - 1) & ~(sizeof(int)-1);

参数类型: ap为va_list类型指针,即为char *,v是最后一个确定的参数。其含义是它之后的参数均为可变参数。

功能:获取可变参数中的第一个参数,并将其地址保存在ap中。

代码语言:javascript
复制
#define _INTSIZEOF(v) ((sizeof(v) + sizeof(int) - 1) & ~(sizeof(int)-1))

_INTSIZEOF(v)宏函数是为了对齐内存。

(2)va_arg

代码语言:javascript
复制
#define va_arg(ap,t) (*(t*))(ap += _INTSIZEOF(t) - _INTSIZEOF(t))

va_arg宏的作用:

参数类型: ap为va_list类型的指针,即char,它指向当前需要获取的参数。t为当前参数的类型。

功能: 获取ap当前所指向参数的指针,并将其强制转化为 *t,并进行解引用 ,然后将ap指向可变参数表的下一个参数。

(3)va_end

代码语言:javascript
复制
#define va_end(ap)  (ap = (va_list)0)
ap = (char*)0 = NULL;

va_end宏的作用:

参数类型: ap为va_list类型的指针 。

功能: 使指针指向空,不在使用该指针。防止ap成为野指针,进行错误引用。实际上通常va_start与va_end是配对使用。

了解并掌握以上三个宏的使用方法以及函数栈调用的规则后。

下面开始分析求和可变参数函数的实现过程:

代码语言:javascript
复制
int average(int n,...)    //...表示参数的类型和数量不确定 n表示传入参数的个数
{
    int sum;
    va_list args;    //相当于定义   char *p;
    va_start(args,n); //获取可变参数列表中的第一个参数的地址并保存在p内 va_start(p,n)
    for(int i = 0;i<n;++i)
    {
        sum += va_arg(args,int);
    }
    va_end(args);   // 等价于*p = NULL;
    return sum;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档