变参函数定义形式如func(type a, …),要求至少一个固定参数,因为需要通过这个参数来确定究竟有多少个参数、以及参数的类型。
windows中,变参函数用来获取参数的几个宏定义如下。
typedef char * va_list;
#define _ADDRESSOF(v) (&(v))
#define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int)-1))
#define va_start(ap,v) (ap=(va_list)_ADDRESSOF(v)+_INTSIZEOF(v))
#define va_arg(ap,t) (*(t*)((ap+=_INTSIZEOF(t))-_INTSIZEOF(t)))
#define va_end(ap) (ap=(va_list)0)
_ADDRESSOF的作用是获取数据的地址,_INTSIZEOF是获取指定类型数据按照int类型对齐的空间大小,va_start就是根据第一个参数来获取第二个参数,va_arg是根据当前参数获取第二个参数。通过这种方法能获取到参数的原因是参数是从右到左依次压入栈的,并且栈是从高地址向低地址生长的,这两个条件决定了可以使用这种方法获取参数。
如上图所示,当调用func(a, b, c, d, e, f, g, h)时,参数会从高地址向低地址压入参数,参数是从右向左的顺序压栈的,第一个参数的地址加上第一个参数的大小便得到了第二个参数的地址,以此类推便可以得到各个参数的地址。