va_list原理及用法

最后更新:2017-02-22

这是一篇很早很早的博客文章,虽然很基础,但是毕竟曾经历程,因此也保存下来

1. 概念

va_list 是在C语言中定义的宏,指在解决

  • 变参问题是指参数的个数不定,可以是传入一个参数也可以是多个;
  • 可变参数中的每个参数的类型可以不同,也可以相同;
  • 可变参数的每个参数并没有实际的名称与之相对应。

2. va_list的用法

  1. 首先在函数里定义一具va_list型的变量,这个变量是指向参数的指针;

  2. 然后用va_start宏初始化变量刚定义的va_list变量;

  3. 然后用va_arg返回可变的参数,va_arg的第二个参数是你要返回的参数的类型(如果函数有多个可变参数的,依次调用va_arg获取各个参数);

  4. 最后用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. 原理解释

  1. 变量

    #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所定义变量为字符指针。
    宏
    
    
  2. _INTSIZEOF 宏,获取类型占用的空间长度,最小占用长度为int的整数倍:

    #define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
    
  3. va_start,获取可变参数列表的第一个参数的地址(ap是类型为va_list的指针,v是可变参数最左边的参数)

    #define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
    
  4. va_arg宏,获取可变参数的当前参数,返回指定类型并将指针指向下一参数(t参数描述了当前参数的类型):

    #define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
    
  5. va_end宏,清空va_list可变参数列表:

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

图解
image_1b9i3i110cb01g4f1p8611vrjmsm.png-11.4kB

posted @ 2017-02-22 20:55  洒水先生  阅读(1848)  评论(0编辑  收藏  举报