可变参数函数参数数量没有固定的数量,通常在传递参数的时候设置第一个参数标识传递参数数量;或者是设置最后一个参数为结束位来标识参数传递结束。
对于可变参数函数,头文件stdarg.h宏定义了几种运算符帮助程序员快速获取可变函数的参数。
1.对于可变参数函数可以使用的几种宏定义
可变参数函数定义:
void test(int a,...);
1、va_list
符号别名定义:typedef char* va_list
声明:va_list ap;
说明:定义一个指针ap
2、va_start
宏定义:#define va_start(ap,v) ((void)(ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v)))
作用:指针ap指向参数a的下一个参数的地址
用法:va_start(ap, a);
说明:当前a的参数类型为int,所以ap = &a + 4
3、va_arg
宏定义:#define va_arg(ap,t) *(t*)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)))
作用:将ap地址加类型t的大小,此时ap指向下一个变量,并且返回ap上一个变量的值。
用法:int b = va_arg(ap, int);
说明:以int型读取ap指向的值
4、va_end
宏定义: #define va_end(ap) ((void)(ap = (va_list)0))
作用:将指针ap指向0x00地址
用法:va_end(ap);
说明:置空指针
2.具体实例
1、设置尾部参数结束标志值
void test(int a , ...)
{
va_list ap;
va_start(ap, a); //确定a下一个参数地址
do
{
int b = va_arg(ap, int); //取ap指向的变量值,ap加变量大小,指向下一个变量
} while (b != -1); //设置结尾参数的值-1为可变参数结束标志值
va_end(ap); //清空指针
}
2、设置第一个参数标识参数数量
void test(int a , ...)
{
va_list ap; //ap指针
va_start(ap, a); //确定a下一个参数地址
while(a--)
{
int b = *ap++; //得到参数值
}
}
3、直接利用va_list返回参数值
void test(int a)
{
char* ap = va_list(1+&a); //此时ap指向参数a的下一个参数,再利用参数的类型来获得指针的数值
}
当然,如果熟悉内存中堆栈的布局,可以完全抛开这些宏定义,直接读取数据值,但是这一些都建立在你知道参数的类型和地址的基础上。