在c语言中,一般来说,函数的参数个数是确定的,并且是根据我们的需要传入指定的参数,但在某些情况下,我们需要可变的参数列表来实现某些功能,因此c语言引入可变参数列表。具体的函数有printf函数,scanf函数等。
一可变参数列表的实现
为了实现可变参数列表,我们通常要用到stdarg.h头文件下的几个函数:
void va_start(va_list ap, last); //va_start用来初始化参数列表t
ype va_arg(va_list ap, type); //va_arg用来获取参数列表中的一个参数,类型为type。
void va_end(va_list ap); //va_end用来清理参数列表。
void va_copy(va_list dest, va_list src); //va_copy用来拷贝参数列表
va_list用来存放参数列表的数据结构。
这些函数以宏的方式实现:
typedef char * va_list; //字符串指针
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1)& ~(sizeof(int) - 1) )
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define va_end(ap) ( ap = (va_list)0 )
二.宏的具体作用
1.va_list
typedef char * va_list; //宏的定义
把char*重命名为va_last,使得va_list定义的指针变量可以访问到未知参数列表
va_list arg;//取自下面的例子
定义了一个char*类型的指针arg,arg指向参数列表。(之所以定义为char*,是为了能取到char类型的变量)
2.va_start
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )//初始化参数列表
_INTSIZEOF(v)的作用是跳过最后一个已知变量v,ap取到未知参数列表的第一个参数,完成参数列表的初始化
va_list arg;
va_start(arg, pos);//取自下面的例子
pos即v,是指向已知参数列表的指针,va_start初始化了最后一个已知参数后面的所有参数。
3.va_arg
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )//取出当前参数
t是未知参数列表中参数的类型。
((ap += _INTSIZEOF(t)) - _INTSIZEOF(t))的作用是使得每次调用va_arg都能使指针自动往后移动一位,本次对本参数访问的同事,下次可以访问到下一个参数。
switch (*pos)//取自下面的例子
{
case ‘s’:s = va_arg(arg, char*);//字符串
cout << s;
break;
case ‘c’:c = va_arg(arg, char);//字符
cout << c ;
break;
case ‘d’:d = va_arg(arg, int);//整型变量
cout << d ;
break;
case ‘%’:
break;
default:
cout <<*pos;
break;
}
pos++;
}
已知参数列表逐步右移,如果遇上%d%c%s,就分别将未知参数列表中的数据以相应的形式输出。
4.va_end
#define va_end(ap) ( ap = (va_list)0 )//清空参数列表
把指向参数列表的指针置为0,达到清理参数列表的目的
三.简单的例子
给出两个简单的例子,大家体验一下实现方式:
简单模拟实现printf
void myprintf(char*pos, ...)
{
assert(pos);
char*s = NULL;
char c = 0;
int d = 0;
va_list arg;
va_start(arg, pos);
while (*pos)
{
switch (*pos)
{
case 's':s = va_arg(arg, char*);//字符串
cout << s;
break;
case 'c':c = va_arg(arg, char);//字符
cout << c ;
break;
case 'd':d = va_arg(arg, int);//整型变量
cout << d ;
break;
case '%':
break;
default:
cout <<*pos;
break;
}
pos++;
}
va_end(arg);
}
int main()
{
myprintf("%d%c%s", 1,'a' ,"bc");
return 0;
}
#include<stdio.h>
#include<stdarg.h>
int MAX(int val, ...)
{
va_list arg;
va_start(arg, val);
int max = 0, temp = 0;
int i = 0;
max = va_arg(arg, int);//因为va_arg没出现一次参数就往后移一个,所以把第一个参数拿下来用来比较
for (i = 1; i < val; i++)
{
if ((temp = va_arg(arg, int))>max)
max = temp;
}
return max;
}
int main()
{
int max = 0;
max=MAX(5, 1, 5, 3, 8, 1);
printf("%d\n", max);
return 0;
}
1万+

被折叠的 条评论
为什么被折叠?



