关闭

可变参数列表

标签: 可变参数列表c语言
83人阅读 评论(0) 收藏 举报
分类:

在很长的一段时间里,我都感觉可变参数列表难!很难! 

今天又遇到了这个难题。起因是要写一个求和的函数,函数的参数不确定。这就需要使用可变参数列表来实现。然我写不出来。脾气上来了决定好好研究一下这个,然后开始查源码,研究了一下突然发现好简单……

可变参数列表是怎么实现的呢?举个例子可能更好理解

现在需要写一个对参数求和的函数,传入的参数不确定。参数原型 int Sum(size_t N,  ...);

接下来需要知道实现可变参数的工具:一个类型va_list,三个宏va_start、 va_arg、 va_end。不要被这四个单词吓着了(虽然今天之前我也是这样)。

va_list:

它的真面目是这样的, typedef char*   va_list;说白了它就是一个char * ,用来定义变量访问访问可变参数。

va_list arg;


va_start:

va_start(arg,N); 
va_start的作用是将arg指向可变参数部分的第一个参数。比如Sum(3,1,2,3); va_start 会将arg指向1。具体操作如下:

(1)拿到N的地址,强转为va_list类型,然后赋给arg

(2)arg向后偏移N的大小个字节,指向N后面的参数,即可变参数的第一个参数

vs2013中的源码是这样的:

#define  va_start   _crt_va_start
#define _crt_va_start(ap,v)  ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
#define _ADDRESSOF(v)   ( &(v) )
#define _INTSIZEOF(n)   ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )<span style="font-size: 12px; font-family: Arial, Helvetica, sans-serif;">//这样写是为了字节对齐,详解http://www.cnblogs.com/diyunpeng/archive/2010/01/09/1643160.html</span>

 

va_arg:

ret += va_arg(arg, int);

va_arg会返回当前arg指向的参数的值,同时会让arg指向下一个参数。具体操作如下:

(1)让arg指向下一个参数,即arg+=sizeof(int);

(2)返回arg之前指向的参数的值,即 *(int*)(arg - sizeof(int))

vs2013中的代码:

#define va_arg   _crt_va_arg
#define _crt_va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define _INTSIZEOF(n)   ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )


va_end:

va_end(arg);
将arg赋为NULL,防止野指针

#define va_end   _crt_va_end
#define _crt_va_end(ap)      ( ap = (va_list)0 )

so 函数Sum的完整实现如下:

int Sum(size_t N, ...)
{
	int ret = 0;
	va_list arg;
	va_start(arg, N);
	while (N--)
	{
		ret += va_arg(arg, int);
	}

	va_end(arg);
	
	return ret;
}




0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:1512次
    • 积分:39
    • 等级:
    • 排名:千里之外
    • 原创:9篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    文章分类