va_list原理及用法

news/2024/12/22 9:43:30/
   VA_LIST 是在C语言中解决变参问题的一组宏,变参问题是指参数的个数不定,可以是传入一个参数也可以是多个;可变参数中的每个参数的类型可以不同,也可以相同;可变参数的每个参数并没有实际的名称与之相对应,用起来是很灵活。

其中va_list( VA_LIST 是在C语言中解决变参问题的一组宏):va_list表示可变参数列表类型,实际上就是一个char指针fmt。

下面是va_list的用法示例

在这里插入图片描述
VA_LIST的用法:
(1)首先在函数里定义一具VA_LIST型的变量,这个变量是指向参数的指针;
(2)然后用VA_START宏初始化变量刚定义的VA_LIST变量;
(3)然后用VA_ARG返回可变的参数,VA_ARG的第二个参数是你要返回的参数的类型(如果函数有多个可变参数的,依次调用VA_ARG获取各个参数);
(4)最后用VA_END宏结束可变参数的获取。
上面是va_list的具体用法,下面讲解一下va_list各个语句含义(如上示例黑体部分)和va_list的实现。

可变参数是由宏实现的,但是由于硬件平台的不同,编译器的不同,宏的定义也不相同,下面是VC6.0中x86平台的定义:

typedef char * va_list; // TC中定义为void*
#define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) ) //为了满足需要内存对齐的系统
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) ) //ap指向第一个变参的位置,即将第一个变参的地址赋予ap
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) /获取变参的具体内容,t为变参的类型,如有多个参数,则通过移动ap的指针来获得变参的地址,从而获得内容/
#define va_end(ap) ( ap = (va_list)0 ) //清空va_list,即结束变参的获取

C语言的函数形参是从右向左压入堆栈的,以保证栈顶是第一个参数,而且x86平台内存分配顺序是从高地址到低地址。因此似函数AVEInt(int var1,int
var2,…,int varN)内存分配大致上是这样的:(可变参数在中间)

在这里插入图片描述
va_list ap; 定义一个va_list变量ap
va_start(ap,v);执行ap = (va_list)&v + _INTSIZEOF(v),ap指向参数v之后的那个参数的地址,即ap指向第一个可变参数在堆栈的地址。
va_arg(ap,t) , ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )取出当前ap指针所指的值,并使ap指向下一个参数。

ap+= sizeof(t类型),让ap指向下一个参数的地址。然后返回ap-sizeof(t类型)的t类型指针,这正是第一个可变参数在堆栈里的地址。然后
取得这个地址的内容。

va_end(ap); 清空va_list ap。

使用VA_LIST应该注意的问题:
(1)因为va_start, va_arg,
va_end等定义成宏,所以它显得很愚蠢,可变参数的类型和个数完全在该函数中由程序代码控制,它并不能智能地识别不同参数的个数和类型.
也就是说,你想实现智能识别可变参数的话是要通过在自己的程序里作判断来实现的.
(2)另外有一个问题,因为编译器对可变参数的函数的原型检查不够严格,对编程查错不利.不利于我们写出高质量的代码。
(3)由于参数的地址用于VA_START宏,所以参数不能声明为寄存器变量,或作为函数或数组类型。
参考博客:
http://hi.baidu.com/kang_liang/blog/item/168c9059a9a1ca2d2934f05f.html
http://fenge.bokee.com/195016.html
http://blog.csdn.net/homer1984/archive/2009/02/02/3859036.aspx


http://www.ppmy.cn/news/222268.html

相关文章

d va爬黑板animate_复合绝缘子的爬电距离(注电案例1295)

某500kV架空输线路工程,最高运行电压550kV,导线采用4JL/GIA−500/45,子导线直径30.0mm,导线自重荷载为16.529N/m。基本风速27m/s,设计覆冰10mm。请回答下列问题。 1295.根据以下情况,计算导线悬…

C语言的va_list使用方法

一、定义 在C中又函数重载功能,C语言中也是又类似功能的,如经常见到的 int fun(char *format, ... ),该函数的参数个数是未定的,以此实现了类似重载的功能,我们用的最多的printf() 函数就是这样实现的,现在来讲讲这个…

Linux 下 va_start、va_end 学习及使用

本文主要介绍可变参数 函数的实现方法。 头文件&#xff1a;#include <stdarg.h> 一、函数系列介绍 1、va_start函数 原型&#xff1a;void va_start(va_list ap, last); ap&#xff1a;va_list 类型的变量&#xff0c;指向参数的指针 last&#xff1a;最后一个显式声明…

va_list(可变参数函数的使用)

A_LIST 是在C语言中解决变参问题的一组宏&#xff0c;变参问题是指参数的个数不定&#xff0c;可以是传入一个参数也可以是多个;可变参数中的每个参数的类型可以不同,也可以相同;可变参数的每个参数并没有实际的名称与之相对应&#xff0c;用起来是很灵活。 va_list 用法示例:…

va_list函数

va_list是用来处理可变参数的&#xff0c;下面看一个示例。 #include "stdarg.h" #include <stdio.h>int test(char* msg, ...);int main() {test("hello", "wolrd",1);return 0; }int test(char* msg, ...) {va_list vaList; //定义一个…

va_start 用法

可以参考&#xff1a;C 标准库 - <stdarg.h> 1. 在C中&#xff0c;当我们无法列出传递函数的所有实参的类型和数目时,可以用省略号指定参数表 void foo(...); void foo(parm_list,...);这种方式和我们以前认识的不大一样&#xff0c;但我们要记住这是C中一种传参的形式…

检测到“_CRT_STDIO_ISO_WIDE_SPECIFIERS”的不匹配项

libboost_thread-vc142-mt-x64-1_82.lib(thread.obj) : error LNK2038: 检测到“_CRT_STDIO_ISO_WIDE_SPECIFIERS”的不匹配项: 值“0”不匹配值“1”(AcadStr.obj 中) 1> 正在创建库 x64\Release\ArxDbg.lib 和对象 x64\Release\ArxDbg.exp : fatal error LNK1319: 检测到 …

va_list分析

typedef char* va_list INTSIZEOF 宏,获取类型占用的空间长度&#xff0c;最小占用长度为int的整数倍&#xff1a; #define _INTSIZEOF(n) ( (sizeof(n) sizeof(int) - 1) & ~(sizeof(int) - 1) ) VA_START宏&#xff0c;获取可变参数列表的第一个参数的地址&#xff08…