原文出自http://www.cppblog.com/xmoss/archive/2009/07/20/90680.html

VA_LIST 是在C语言中解决变参问题的一组宏

他有这么几个成员:

1) va_list型变量:

#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

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)首先在函数里定义一具VA_LIST型的变量,这个变量是指向参数的指针;
       (2)然后用VA_START宏初始化变量刚定义的VA_LIST变量;
       (3)然后用VA_ARG返回可变的参数,VA_ARG的第二个参数是你要返回的参数的类型(如果函数有多个可变参数的,依次调用VA_ARG获取各个参数);
       (4)最后用VA_END宏结束可变参数的获取。
使用VA_LIST应该注意的问题:
   (1)可变参数的类型和个数完全由程序代码控制,它并不能智能地识别不同参数的个数和类型;
   (2)如果我们不需要一一详解每个参数,只需要将可变列表拷贝至某个缓冲,可用vsprintf函数;
   (3)因为编译器对可变参数的函数的原型检查不够严格,对编程查错不利.不利于我们写出高质量的代码;

小结:可变参数的函数原理其实很简单,而VA系列是以宏定义来定义的,实现跟堆栈相关。我们写一个可变参数的C函数时,有利也有弊,所 以在不必要的场合,我们无需用到可变参数,如果在C++里,我们应该利用C++多态性来实现可变参数的功能,尽量避免用C语言的方式来实现。
本文参考:http://hi.baidu.com/kang_liang/blog/item/168c9059a9a1ca2d2934f05f.html

【转】va_list 详解的更多相关文章

  1. [转载]va_start和va_end使用详解

    va_start和va_end使用详解 原文地址:http://www.cnblogs.com/hanyonglu/archive/2011/05/07/2039916.html 本文主要介绍va_s ...

  2. [转载]C/C++可变参数之va_start和va_end使用详解

    本文主要介绍va_start和va_end的使用及原理. 在以前的一篇帖子Format MessageBox 详解中曾使用到va_start和va_end这两个宏,但对它们也只是泛泛的了解. 介绍这两 ...

  3. [转]va_start和va_end使用详解

    转载地址:http://www.cnblogs.com/hanyonglu/archive/2011/05/07/2039916.html  本文主要介绍va_start和va_end的使用及原理. ...

  4. 20160129.CCPP体系详解(0008天)

    程序片段(01):函数.c+call.c+测试.cpp 内容概要:函数 ///函数.c #include <stdio.h> #include <stdlib.h> //01. ...

  5. 20160217.CCPP体系详解(0027天)

    程序片段(01):TestCmd.c 内容概要:管道_字符串 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include < ...

  6. JNI详解---从不懂到理解

    转载:https://blog.csdn.net/hui12581/article/details/44832651 Chap1:JNI完全手册... 3 Chap2:JNI-百度百科... 11 C ...

  7. JSPatch实现原理详解<二>

    本文转载至 http://blog.cnbang.net/tech/2855/ 距离上次写的<JSPatch实现原理详解>有一个月的时间,在这段时间里 JSPatch 在不断地完善和改进, ...

  8. va_start和va_end使用详解(转载)

    转自:http://www.cnblogs.com/hanyonglu/archive/2011/05/07/2039916.html 本文主要介绍va_start和va_end的使用及原理. 在以前 ...

  9. ffmpeg 详解

    来源:http://blog.itpub.net/9399028/viewspace-1242300/ FFMPEG详解   认识FFMPEG FFMPEG堪称自由软件中最完备的一套多媒体支持库,它几 ...

随机推荐

  1. blender, fbx导入blender进行编辑

    fbx文件导入blender后,直接点下面Object Mode弹不出下拉菜单,从而无法进入Edit Mode.解法是先点一下右边Scene层级列表中的Sphere节点,将其选中,然后再点下面的Obj ...

  2. OpenJudge百炼习题解答(C++)--题4074:积水量

    题: 总时间限制: 1000ms       内存限制:65536kB 描写叙述 凹凸不平的地面每当下雨的时候总会积水.如果地面是一维的.每一块宽度都为1,高度是非负整数.那么能够用一个数组来表达一块 ...

  3. Python学习笔记7:函数对象及函数对象作參数

    一.lambda函数 比如: fun1 = lambda x,y: x + y print fun1(3,4) 输出:7 lambda生成一个函数对象.该函数參数为x,y,返回值为x+y.函数对象赋给 ...

  4. 【Unity】Unity中资源动态载入的两种方式之AssetsBundle

    首先要说的是,我们的project中有2个脚本.各自是: Build(编辑器类脚本.无需挂载到不论什么物体).可是必需要把Build脚本放到Editor目录中 Load脚本,挂载到摄像机上<pr ...

  5. AJax与Jsonp跨域访问

    一.JavaScript的AJax AJAX即"Asynchronous Javascript And XML"(异步JavaScript和XML) 设计AJax使用的一种重要技术 ...

  6. SAM I AM UVA - 11419 最小点集覆盖 要输出具体覆盖的行和列。

    /** 题目:SAM I AM UVA - 11419 链接:https://vjudge.net/problem/UVA-11419 题意:给定n*n的矩阵,'X'表示障碍物,'.'表示空格;你有一 ...

  7. android之ViewPager修改滑动速度

    在android中,使用过viewpager的人都清楚,我们如果使用viewpager进行滑动时,如果通过手指滑动来进行的话,可以根据手指滑动的距离来实现,但是如果通过setCurrentItem函数 ...

  8. 从客户端检测到有潜在危险的Request.Form 值”错误提示

    http://www.cnblogs.com/UouHt/archive/2008/10/30/1322697.html asp.net开发中,经常遇到“从客户端检测到有潜在危险的Request.Fo ...

  9. Torch-RNN运行过程中的坑 [0](一些基础概念)

    0.Lua & LuaJIT简介 Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能. Lua 是巴 ...

  10. 探讨instanceof实现原理,并用两种方法模拟实现 instanceof

    在开始之前先了解下js数据类型 js基本数据类型: null undefined number boolean string js引用数据类型: function object array 一说ins ...