最后更新: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 )

图解

va_list原理及用法的更多相关文章

  1. Nmap扫描原理与用法

    Nmap扫描原理与用法 1     Nmap介绍 Nmap扫描原理与用法PDF:下载地址 Nmap是一款开源免费的网络发现(Network Discovery)和安全审计(Security Audit ...

  2. PHP依赖注入原理与用法分析

    https://www.jb51.net/article/146025.htm 本文实例讲述了PHP依赖注入原理与用法.分享给大家供大家参考,具体如下: 引言 依然是来自到喜啦的一道面试题,你知道什么 ...

  3. JSON Web Token(JWT)原理和用法介绍

    JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案.今天给大家介绍一下JWT的原理和用法. 官网地址:https://jwt.io/ 一.跨域身份验证 Internet服务无法与 ...

  4. Java并发-volatile的原理及用法

    Java并发-volatile的原理及用法 volatile属性:可见性.保证有序性.不保证原子性.一.volatile可见性 在Java的内存中所有的变量都存在主内存中,每个线程有单独CPU缓存内存 ...

  5. NSPredicate用法总结(Cocoa框架中的NSPredicate用于查询,原理和用法都类似于SQL中的where,作用相当于数据库的过滤取)

    简述:Cocoa框架中的NSPredicate用于查询,原理和用法都类似于SQL中的where,作用相当于数据库的过滤取. 定义(最常用到的方法): NSPredicate *ca = [NSPred ...

  6. Web安全学习笔记之Nmap扫描原理与用法

    1     Nmap介绍 Nmap扫描原理与用法PDF:下载地址 Nmap是一款开源免费的网络发现(Network Discovery)和安全审计(Security Auditing)工具.软件名字N ...

  7. 初涉IPC,了解AIDL的工作原理及用法

    初涉IPC,了解AIDL的工作原理及用法 今天来讲讲AIDL.这个神奇的AIDL,也是近期在学习的,看了某课大神的解说写下的blog,希望结合自己的看法给各位同价通俗易懂的解说 官方文档:http:/ ...

  8. 41、扩展原理-ApplicationListener用法

    41.扩展原理-ApplicationListener用法 ApplicationListener 监听容器中发布的事件.事件驱动模型开发: public interface ApplicationL ...

  9. Python实现的选择排序算法原理与用法实例分析

    Python实现的选择排序算法原理与用法实例分析 这篇文章主要介绍了Python实现的选择排序算法,简单描述了选择排序的原理,并结合实例形式分析了Python实现与应用选择排序的具体操作技巧,需要的朋 ...

随机推荐

  1. 剑指Offer编程题(Java实现)——链表中环的入口结点

    题目描述 给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null. 思路一 迭代遍历链表,利用HashSet将每个结点添加到哈希表中,如果添加失败(重复遍历了这个结点即遇到环),输出 ...

  2. 各类最新Asp .Net Core 项目和示例源码

    1.网站地址:http://www.freeboygirl.com2.网站Asp .Net Core 资料http://www.freeboygirl.com/blog/tag/asp%20net%2 ...

  3. zebra代码分析

    http://blog.csdn.net/xuyanbo2008/article/details/7439738

  4. 【ES6】对象的新功能与解构赋值

    ES6 通过字面量语法扩展.新增方法.改进原型等多种方式加强对象的使用,并通过解构简化对象的数据提取过程. 一.字面量语法扩展 在 ES6 模式下使用字面量创建对象更加简洁,对于对象属性来说,属性初始 ...

  5. 客户端通过url向后端传递参数

    在前端我们不仅可以通过get请求携带参数的方式向服务端传数据: https://127.0.0.1/index/?id=1&name=alex Django也允许通过,path路径的方式向se ...

  6. css重置的各种版本总结

    个人手机端常用到的: @charset "utf-8"; body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, dl, dt, dd, ...

  7. C++ constexpr

    1.constexpr 1.const与constexpr: const: 承若不改变这个值,主要用于说明接口,这样在把变量传入函数时就不必担心变量会在函数内被改变了,编译器负责确认并执行const的 ...

  8. js 全世界最短的IE浏览器判断代码

    var ie = !+"\v1"; 仅仅需要7bytes!参见这篇文章,<32 bytes, ehr ... 9, ehr ... 7!!! to know if your ...

  9. reactV16理解

    在 V16 版本中引入了 Fiber 机制.这个机制一定程度上的影响了部分生命周期的调用,并且也引入了新的 2 个 API 来解决问题. 在之前的版本中,如果你拥有一个很复杂的复合组件,然后改动了最上 ...

  10. 搭建jumperserver堡垒机管理万台服务器-1

    搭建jumperserver堡垒机管理万台服务器-1 1  Jumpserver堡垒机概述-部署Jumpserver运行环境 2  安装Coco组件 3  安装Web-Terminal前端-Luna组 ...