【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