【C/C++】不定参数函数
文章结构:
不定参数函数形式
在标准库中,某些函数的参数数量是不固定,是可变的,例如print()
等。
不定参数的形式一般为:
type function_name(type arg1, [type arg_n], ...) {
va_list list_args;
... ...
}
在函数的参数中,第一个参数是一定要声明确切的类型及参数名的,之后的参数可以声明类型及参数名,也可以直接用...
来代替表示不定参数。
函数体在执行过程中需要知道...
所表示的不定参数的具体类型,所以如系统的print()
函数第一个参数是char*
并用%[flag]
中的flag
来告诉函数第n个参数的具体类型。即,要嘛所有参数固定为已知类型,如求平均值时都固定为float
;要嘛在类型不固定的情况下需要由arg1
或arg_n
来告诉函数后续...
的具体参数类型。
在不定参数函数体的开头,都要声明一个va_list
的对象以便后续被下面的宏定义所使用。
宏定义讲解
不定参数函数的实现需要包含stdarg.h
头文件的支持。
该头文件中定义了一个宏,而非函数(虽然看起来像函数)来支持不定参数函数的实现。
#include <stdarg.h>
void va_start(va_list list_args, last);
va_start()
是要获取参数之前要对va_list
进行初始化操作,所以va_start()
必须在va_arg()
和va_end()
之前执行。last
参数是指在函数声明中确定类型及名称的最后一个参数。这个last
参数不应代表寄存器变量、函数指针或数组。
type va_arg(va_list ap, type);
va_arg()
函数第一次执行时返回va_start()
中last
的下一个参数,之后的每次执行都会继续返回va_list
的下一个;第二个参数type
指定当前要返回的参数的具体类型。
如果va_list
已经到结尾了,或者type
与参数的实际类型是不符合的,则会发生未知的错误。
void va_end(va_list ap);
当va_end()
必须与va_start()
在同一个函数体中成对出现,在执行完va_end()
之后va_list ap
就被失去了定义了,变为不可用状态。
如果想多次遍历va_list ap
,则可以通过再次调用va_start()
后继续遍历,在遍历结束后要相应的调用va_end()
结束遍历。
void va_copy(va_list dest, va_list src);
对va_list
进行复制。src
是执行va_start()
之后已经初始化了的。且在src
执行完va_end()
之前,不能将dest
用于另一个遍历的过程。
示例代码:实现print()函数
以下代码模拟实现了系统函数printf()
的功能:
1 |
|
最后输出如下:
sodino@qq.com, 123 456 P Q varying arguments
Program ended with exit code: 0