一、VA_LIST
VA_LIST 是在C语言中解决变参问题的一组宏,用于获取不确定个数的参数。
1、用法
(1). 首先在函数里定义一具VA_LIST型的变量,这个变量是指向参数的指针;
(2). 然后用VA_START宏初始化刚定义的VA_LIST变量;
(3). 然后用VA_ARG返回可变的参数,VA_ARG的第二个参数是你要返回的参数的类型(如果函数有多个可变参数,依次调用VA_ARG获取各个参数;
(4). 最后用VA_END宏结束可变参数的获取;
2、成员详解
(1). VA_START宏:获取可变参数列表的第一个参数的地址。va_start(ap,v)(ap是类型为va_list的指针且ap指向第一个变参的位置,即将第一个变参的地址赋予ap,v是可变参数最左边的参数);
(2). VA_ARG宏:获取可变参数的当前参数,返回指定类型并将指针指向下一参数。va_arg(ap,t)(t参数描述了当前参数的类型);
(3). VA_END宏:清空va_list可变参数列表。
3、通过栈进一步理解
C语言的函数形参是从右向左压入堆栈的,以保证栈顶是第一个参数,而且x86平台内存分配顺序是从高地址到低地址。因此似函数AVEInt(int var1,int var2,…,int varN)内存分配大致上是这样的:(可变参数在中间)
栈区:
|栈顶 低地址
|第一个参数var1 <– &v
|第二个参数var2 <– va_start(ap,v)后ap指向地址
|…
|函数的最后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。
注意:如果我们不需要一一详解每个参数,只需要将可变列表拷贝至某个缓冲,可用vsprintf函数;
二、vsnprintf
vsnprintf将可变参数格式化输出到一个字符数组
1、函数简介
(1)、函数原型:int vsnprintf(char *str, size_t size, const char *format, va_list ap);
参数:
(2)、str输出到的数组,size指定大小,防止越界,format格式化参数,ap可变参数列表函数用法