C语言的可变参函数

来源:互联网 发布:淘宝美工详情页模板 编辑:程序博客网 时间:2024/06/05 15:26

C语言的可变参函数

1.什么是可变参函数

可变参函数,顾其名而思义,就是该函数的参数数目不固定,例如我们的格式化输出函数

 int printf(const char *fmt, ...)

这个函数的“…”参数就代表它是个可变参的函数。这个函数第一个参数一定是一个字符串,通过字符串中的“d%”,“%s”等等来对应后面的参数数量,这样以来就可以正确解析函数的参数。

2.可变参函数的原理

实现可变参函数,依赖于三个宏和一个数据类型
三个宏分别是va_arg, va_end, va_start
一个数据类型则是va_list

2.1 va_list类型

va_list 的 va是variable-argument(可变参数)。list则就是列表的意思,但它到底是什么呢?

   typedef char *va_list;//Linux内核中va_list的实现

原来,va_list就是一个char *的数据类型。

2.2 va_start

va_start是一个宏定义,接收两个参数

    #define va_start(ap, A)     //Linux内核中宏定义的原型在此    (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND))))

第一个参数ap,就是刚才提到的va_list 类型,第二个参数A,就是一个确定的类型,也就是“…”的类型,它会将这些类型的地址放到va_list中,根据初始化A来初始化ap。

2.3 va_arg

va_arg是一个宏定义,接收两个参数

    #define va_arg(ap, T)       //Linux内核中宏定义的原型在此    (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADN    BND))))

ap 也是va_list类型, T是一个类型。从参数列表中取出一个参数,类型就是T

2.4va_end

va_end是一个宏

    #define va_end(ap)          (ap = (va_list) NULL)

通过这个宏,可以清楚的看到,将va_list类型的ap赋值为NULL。

2.5 这些宏怎么合作?

通过va_start初始化参数列表(得到具体的参数个数),参数列表由va_list定义,然后使用va_arg从参数列表中取出参数并处理,最后调用va_end来清理参数列表。

3. 可变参数函数的例子

格式化输出printf()函数在Linux内核中的源码:

    int printf(const char *fmt, ...)    {        char printf_buf[1024];        va_list args;  //定义参数列表args        int printed;        va_start(args, fmt);  //用fmt初始化args        printed = vsprintf(printf_buf, fmt, args);//在vsprintf()中调用了va_arg的宏来处理每一个参数        va_end(args);//清理参数列表        puts(printf_buf);        return printed;    }

编写一个可变参的求和函数:

    int sum(int cnt,...)    {        int sum=0;        int i;        va_list ap;//定义可变参数列表        va_start(ap,cnt);//用cnt初始化ap        for(i=0;i<cnt;++i)             sum+=va_arg(ap,int);//根据int类型从ap取出参数并处理        va_end(ap);//清理参数列表        return sum;    }

4. 可变参数函数的总结

  • 可变参数函数必须有非可变的参数,并且位于可变参数的前面
  • 编写可变参函数的人必须控制可变参的类型以及可变参的数目
  • 可变参的个数必须通过非可变参数来获取
0 0
原创粉丝点击