1. 简介
可否想过 C 语言中最常见常用的 printf() 函数是如何做到接收任意类型、任意数量的参数的呢?
实际上,printf() 中通过可变参数特性来接收任意类型、任意数量的参数。可变参数通过占位 ...
显式指示,例如以下函数的形参就是可变参数:
void fun (...)
{
// do something
}
2. 相关 API
在函数中怎么使用这些可变参数呢?C 语言在头文件 <stdarg.h> 中提供了三个操作可变参数的 API:va_start
、va_arg
、va_end
,前缀 va 即 variable argument(可变参数)。
这三个 API 都为函数宏,功能如下:
- va_start
va_start
的声明如下(伪代码):
void va_start (va_list ap, last);
ap
为可变参数列表对象,需要在调用 va_start
前创建。va_list
内包含一个成员指针,即 ap
内有指向可变参数的指针。
last
为可变参数的占位符前的形参。一般情况下,使用可变参数的函数需要提供一个形参用于函数调用时指定可变参数的个数,否则在程序中将无法得知具体的可变参数个数。
va_start
用于初始化可变参数列表对象,把 ap
内的可变参数指针指向 last
的下一个参数即可变参数列表的第一个参数。
- va_arg
va_arg
的声明如下(伪代码):
type va_arg (va_list ap, type);
type
为可变参数的数据类型。
va_arg
用于获取 ap
的可变参数参数指针所指的参数并作为返回值。获取后该指针将根据 type
偏移一定字节数,指向下一个可变参数。
需要注意的是,使用 GCC 编译时,当可变参数类型为 char 或 short 即少于四个字节,可变参数将占据四个字节大小。因此,此时的函数实参 type
应显式指示为 int。
- va_end
va_end
的声明如下(伪代码):
void va_end (va_list ap)