在C语言中想在函数参数列表中传入不固定数量和类型的参数,可以使用stdarg.h
头文件,该头文件定义了一系列宏用以实现可变参数列表。
实际上,最熟悉的printf
、scanf
函数就是这么实现的。
用法
1 |
|
- 在函数参数列表中,提供一或多个有名称的参数,最后跟上
...
提示此处传递数量和类型未知的参数。 - 用
va_list
类型声明一个变量用于访问可变参数列表。 va_start()
接受一个va_list
变量和最后一个有名称参数用于初始化,将该va_list
变量设置为指向第一个可变参数列表的参数(由给定的最后一个有名称的参数通过相对偏移来确定位置)。va_arg()
接受一个va_list
变量和类型名称,按类型返回当前位置参数的值,并将va_list
变量向后移动。va_end()
用于将va_list
置空,并完成一些清理工作。
注意
- 可变参数传递过程中会发生默认参数提升,也就是说没有char/short/float型,因为它们已经被提升了。(详见默认参数提升或见**参考**部分相关文章)现在编译器很智能,当你试图使用这些类型访问时会给出警告:
-
va_end()
是必须的。有人认为va_end()
是不必要的,因为其编译环境下该函数只作了对va_list
置空操作。但不同编译环境下,有可能va_start()
可能以某种方式修改了堆栈,这种修改可能导致返回无法完成,va_end()
会将其复原;当然也可能有其他实现。因此,基于可移植性的考虑,va_end
当然是必须的。
参考
- 《Pointers On C》
- 可变长参数列表误区与陷阱——va_arg不可接受的类型
- 可变长参数列表误区与陷阱——va_end是必须的吗?