va_list原理及用法
最后更新:2017-02-22
这是一篇很早很早的博客文章,虽然很基础,但是毕竟曾经历程,因此也保存下来
1. 概念
va_list 是在C语言中定义的宏,指在解决
- 变参问题是指参数的个数不定,可以是传入一个参数也可以是多个;
- 可变参数中的每个参数的类型可以不同,也可以相同;
- 可变参数的每个参数并没有实际的名称与之相对应。
2. va_list的用法
-
首先在函数里定义一具va_list型的变量,这个变量是指向参数的指针;
-
然后用va_start宏初始化变量刚定义的va_list变量;
-
然后用va_arg返回可变的参数,va_arg的第二个参数是你要返回的参数的类型(如果函数有多个可变参数的,依次调用va_arg获取各个参数);
-
最后用va_end宏结束可变参数的获取。
例如
- (NSArray *)combine:(NSString *)string, ... { NSMutableArray *arrayM = [NSMutableArray array]; [arrayM addObject:string]; va_list list; id tag; va_start(list, string); while ((tag = va_arg(list, id))) { [arrayM addObject:tag]; } va_end(list); return [arrayM copy]; }
3. 原理解释
-
变量
#ifdef _M_ALPHA typedef struct { char *a0; /* pointer to first homed integer argument */ int offset; /* byte offset of next parameter */ } va_list; #else typedef char * va_list; #endif _M_ALPHA是指DEC ALPHA(Alpha AXP)架构。所以一般情况下va_list所定义变量为字符指针。 宏
-
_INTSIZEOF 宏,获取类型占用的空间长度,最小占用长度为int的整数倍:
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
-
va_start,获取可变参数列表的第一个参数的地址(ap是类型为va_list的指针,v是可变参数最左边的参数)
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
-
va_arg宏,获取可变参数的当前参数,返回指定类型并将指针指向下一参数(t参数描述了当前参数的类型):
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
-
va_end宏,清空va_list可变参数列表:
#define va_end(ap) ( ap = (va_list)0 )
图解