可变参数列表
Posted _NiuLi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了可变参数列表相关的知识,希望对你有一定的参考价值。
在很长的一段时间里,我都感觉可变参数列表难!很难!
今天又遇到了这个难题。起因是要写一个求和的函数,函数的参数不确定。这就需要使用可变参数列表来实现。然我写不出来。脾气上来了决定好好研究一下这个,然后开始查源码,研究了一下突然发现好简单……
可变参数列表是怎么实现的呢?举个例子可能更好理解
现在需要写一个对参数求和的函数,传入的参数不确定。参数原型 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(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;
以上是关于可变参数列表的主要内容,如果未能解决你的问题,请参考以下文章