1.背景
在C中,当我们无法列出传递函数的所有参数的类型和数目时,可以用省略号指定参数表
如我们常用的打印输出
int printf(const char *format, ...);
这也是C中一种传参的形式。
2、函数参数的传递原理
函数参数以数据结构---栈的形式存取,从右到左入栈。
以void func(int x, float y, char z);函数而言,调用时,实参z先入栈,在y入栈,最后x入栈。理论上只要探测到任意一个变量的地址,且知道其他变量的类型,就可以通过指针移位运算,顺藤摸瓜找到其他的输入变量。
3、可变参函数func(int num_param, ...)
根据参数传递原理,我们可以根据num_param的地址,通过指针移位,找出其他的输入变量。ANSI C标准提供一种方法帮助我们查找。
3.1 可变参函数如何获取变量
根据<stdarg.h>头文件中的va_start、va_arg、va_end三个宏函数来获取可变参数。
看在<stdarg.h>头文件中宏定义
typedef char * va_list //步骤1、定义一个字符指针,
void va_start(va_list ap, prev_param); //步骤2、ap初始化,让它指向可变参数中的第一个参数,即prev_param
type va_arg(va_list ap, type); //步骤3、根据类型获取参数,同时ap的位置指向参数表的下一个变量的位置
void va_end(va_list ap); //关闭ap指针,取完参数表后关闭指针
3.2 举个栗子
实现int myprintf(const char *format, ...);
int myprintf(const char *format, ...)
{
char *p;
va_list ap;
int ival;
double dval;
char *s;
if(format == NULL)
return -1;
va_start(ap, format);
for(p = format, *p, p++)
{
if(*p != '%')
{
putchar(*p);
continue;
}
switch(*(++p))
{
case 'd':
ival = va_arg(ap, int);
printf("%d", ival);
break;
}
}
}