可变参数
- 参数个数可变
- 参数类型可变
原理概述
由于在函数调用时,参数通过栈进行传递(stdcall、cdecl)而且参数入栈时会按照顺序依次入栈。
所以在被调用的函数内,知道了第一个参数的地址就可以根据类型获得其他参数的地址从而获取参数的值.
这里需要注意的一点:
上面提到的stdcall和cdecl是说明这两种参数都是通过栈传递,但是只有cdecl支持可变参数,因为cdecl由调用者维护栈平衡
另外,可变参数的限制有两个:
- 必须知道第一个参数的地址,也就是说函数内不能全部都是可变参数。可以把第一个参数设置为可变参数的数量,因为可变参数类型可变,个数可变,并不能规定一个通用的结束标志。例如printf这样的函数,都是根据第一个字符串内的%d这样占位符的数量确定参数个数,所以后面的可变参数不匹配就会出错甚至崩溃
- 必须知道每个参数的类型,因为不知道参数确切的类型,即使参数排列在连续的内存区域但是仍然无法知道每个参数的起始地址。这也是printf需要使用%d,%f这样来区分类型的原因
具体实现
头文件:stdarg.h
用到的宏:
宏 | 功能 | 参数说明 |
---|---|---|
va_list | 可变参数类型,实际上是一个char* 指针 | |
va_start | 初始化va_list | 传入va_list对象和起始参数 |