可变参数列表的实现

      在学习C语言的过程中,大家是不是和我一样,认为printf是一个神一样的函数?他可以接受不同数目不同类型的参数,他到底是怎么实现的呢?

让我们去看一下它的源代码:

printf源代码:

int printf(const char *fmt,...)
{
	int res;
        va_list arg;
	va_start(arg,fmt);
	res = vprintf(fmt,arg);
	va_end(arg);
	return res;
}

它采用的是可变参数列表,可变参数列表主要有以下两个缺点:

     1)无法确定可变参数列表的长度,这也是printf提供通配符的原因所在

     2)不能提供类型检查,在实参向形参的拷贝过程中可能会出现问题,一般建议只传递基本数据类型


一个类型:va_list ;三个宏:va_start ;


首先介绍一个用可变参数列表实现的一个函数,在分别介绍他们(一类型,三宏)

#include<stdarg.h>
#include<iostream>
using namespace std;
 /*可变参数列表实现求一组不确定数目数值的和*/
int sum(int n,int v1,...)
{
	va_list arg;
	va_start(arg,v1);
	int sum = v1;

	for(int i=0;i<n-1;++i)/*第一个数一开始就加入sum中,所以剩余n-1个数,所以需要加n-1次*/
	{
		int tmp = va_arg(arg,int);
		sum += tmp;
	}
	va_end(arg);

	return sum;
}

int main()
{
	int ret = sum(4,1,2,3,4);
	cout<<ret<<endl;
	return 0;
}



1、va_list

    1)用法

int sum(int n,int v1,...)
{
	va_list arg;
	。。。。。。。
}

     如上,定义了一个 va_list类型的变量 arg,可以用该变量作为保存可变参数列表的指针。实际使用中,如果把可变参数列表的入参看做一个数组 array,那么这个 va_list 就相当于其迭代器 iterator

    这个宏本身只是个定义,真正赋予其意义的在于下面的几个宏。

    2)实现:实际上只是一个 char * 类型的指针,原因这里不能判定类型,所以用size为1的char类型指针会方便移动。


2、va_start

    1)用法:

int sum(int n,int v1,...)
{
	va_list arg;
	va_start(arg,v1);
	。。。。。。
}

           这个宏需要两个参数,第一个是上面定义的 va_list, 第二个是可变参数列表之前的那个参数。

    作用就是使得 va_list 的变量指向可变参数列表的首地址。这才是一般意义上的对 va_list的初始化。

    2)实现

#define va_start ( ap, v ) ( ap = (va_list)&v + _INTSIZEOF(v) ) 


    很容易看懂,就是将ap指向v后的地址。

   3)注意:

   按照规范,va_start中的参数,一定要是最后一个参数,也就是...之前的那个参数,不然可能会有问题。尤其是windows和linux的函数参数入栈顺序不同,会有可移植性问题


3、va_arg

    1)用法:

int tmp = va_arg(arg,int);


    同样有两个参数,第一个是前面va_list已经初始化好的变量arg第二个参数是类型,比如这里可变参数列表的第一个参数是int类型,那么就传int。

    这个函数实现了类似于迭代器的功能,他的返回值是当前itor指向的 int类型值(类型是第二个参数所描述的),同时会移动 itor,使得其指向可变参数列表的下一个参数。

4、va_end

    1)用法:

	va_end(arg);

    2)实现:这个宏实际上是个空实现,更多是提高代码的可读性,同时方便后面的扩展。


5、缺少的....

    作为一个迭代器,缺少的最关键一环就是判定结尾,可惜这里是没法提供的。还是老老实实的结尾传个NULL吧。




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值