可变参数

可变参数是指函数的参数的数据类型和数量都是不固定的。

例如printf()函数的参数就是可变的。这个函数的原型是:int printf(const char *format,...)

实现

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>

void foo(int count, ...)
{
printf("hello I am foo\n");

va_list parameters;//va_list变量
va_start(parameters,count);//初始化,count是形参个数
for(int i=0;i<count;i++)
{
void* parameter = va_arg(parameters,void*);
printf("%p\n",(int*)parameter);

}

va_end(parameters);
}
  • 定义

一个函数,最后一个参数为省略号,省略号前面可以设置自定义参数。

  • va_list

在函数定义中创建一个 va_list 类型变量,该类型是在 stdarg.h 头文件中定义的。它包含了参数信息,这种类型的对象也被称为参数指针。它包含了栈中至少一个参数的位置,可以使用它从一个可选参数到下一个。

  • va_start

使用 int 参数和 va_start 宏来初始化 va_list 变量为一个参数列表。宏 va_start 是在stdarg.h头文件中定义的。宏 va_start 使用第一个可选参数的位置来初始化 va_list 参数指针。该宏的第二个参数必须是该函数最后一个有名称参数的名称。必须先调用该宏,才可以开始使用可选参数。

void va_start(va_list argptr, lastparam);
  • va_arg

使用 va_arg 宏和va_list变量来访问参数列表中的每个项。展开宏 va_arg 会得到当前参数指针所引用的可选参数,也会将参数指针移动到列表中的下一个参数。宏 va_arg 的第二个参数是刚刚被读入的参数的类型。

type va_arg(va_list argptr, type);
  • va_end

使用宏 va_end 来清理赋予 va_list 变量的内存。当不再需要使用参数指针时,必须调用宏 va_end。如果想使用宏 va_start 或者宏 va_copy 来重新初始化一个之前用过的参数指针,也必须先调用宏 va_end

void va_end(va_list argptr);

void*

void被翻译为“无类型”,相应的void*为“无类型指针”。

void*指针变量可以指向任意变量的内存空间,任意类型指针变量都可以转换为void*

int num = 10;
void* p = &num;
int* p_num = &num;
void* p1 = p_num;

对于void*指针变量,不要解除引用操作,如果想通过指针变量p获取num的值,需要强制类型转换

int* p_num = (int*)p;
cout<< *p <<endl;