一、在介绍va_list之前,首先介绍众所周知的printf()函数的实现,请看下面的代码:
int printf(char const* __restrict fmt,...)
{
va_list arg_ptr;
va_start(arg_ptr,fmt);
int ret = vfprintf(stdout,fmt,arg_ptr);
va_end(arg_ptr);
return ret;
}
printf函数的形参列表长度是可变的,这种函数被称为变参函数,即参数的个数不确定。相比C++中的重载中对参数的个数的限制,变参函数使用起来比较灵活。
下面看下该函数是如何显现的。其主要使用的va_list类型才使得printf函数具有如此的灵活性。所以printf的使用灵活性应归功于va_list。
二、可变参函数的声明
在无法给出所有传递给函数的参数的类型和数目时,可以使用省略号(...)指定函数参数表。有如下几种形式:
1 void fun1(int a, double b, ...); //给出确定的几个参数,其他用省略号
2 void fun2(int a ...); //省略号前有或者没有逗号都是可以的
3 void fun3(...); //也可以不确定任何参数,但和没有参数是不一样的
三、va_start,va_arg,va_end三个宏的介绍:
下面三个宏是来调用操作可变参数:
#include <stdarg.h>
void va_start(
va_list arg_ptr, //指向参数列表的指针
prev_param //最后一个显式声明的参数,以用来获取第一个可变参数的位置
);
type va_arg(
va_list arg_ptr,
type //要获取的参数类型,如char,int,float等
);
void va_end(
va_list arg_ptr
);
四、va_start,va_arg,va_end三个宏的使用:
1、定义一个va_list变量,该变量是指向可变参数的指针。
2、使用va_start初始化刚刚声明的va_list变量。第二个参数是可变参数最后一个显式声明的参数。
3、使用va_arg返回可变参数的值,第二个参数是该可变参数的类型。注意需要确定va_list变量是否是指向你想要的变量。
4、使用va_end清空第一步声明的va_list变量为NULL.
注意:1、可变参数的类型和数目不能通过这三个宏来获取,只能通过程序来控制。
五、具体使用详见第一部分的printf函数的实现。
六、关于va_list和这三个宏是如何定义,请自行查看MFC中头文件stdio.h,stdarg.h。当然不用的编译器,有不同的定义。