<stdarg.h>提供了以下数据类型和宏,以便我们编写长度可变的函数
typedef char * va_list;
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
#define va_end(ap) ( ap = (va_list)0 )
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
实现可变参数的方法就是把函数的第一个参数的值设为可变参数的个数,然后用以上几个宏把参数读出来
使用方法:
假设有这么一个函数test(int num, ...);,且可变参数的类型都是int
那么第一步是声明一个va_list变量ap,然后调用va_start(ap, num)使ap指向可变参数的第一个参数。
第二步使用int value = va_arg(ap, int)读出这一个可变参数的值,同时ap也被指向了下一个可变参数
重复第二步num次,最后使用va_end(ap)避免ap称为野指针
其实认真的读代码,这几个宏真的不难理解
_INSIZEOF(n) 的功能是得到n的sizeof(int)向上取整的值
va_start(ap, v) 的功能是是ap跳过v这个参数,从而指向第一个参数,因为这考虑到对齐,v的类型占的字节数一定要是int类型的整数倍,所以需要向上取整
va_arg(ap ,t) 就是读取这个位置参数的值,并且将ap指向下一个参数,下一个参数的位置就是ap 加上t这个类型所占的字节数,这里一样要向sizeof(int)上取整
va_end(ap)就跟简单了,就是把ap赋为0,防止我们访问野指针