可变参数列表

来源:互联网 发布:数据库人员报表查询 编辑:程序博客网 时间:2024/05/16 15:53

可变参数列表可以让函数在不同的时候接受不同数目的参数,可变参数列表是通过宏来实现的,这些宏定义于stdarg.h头文件,它是标准库的一部分。这个头文件声明了类型va_list和三个宏——va_start,va_arg和va_end,接下来我们通过一个求平均值的函数来观察这三个宏。

例子一:

#include<stdio.h>
#include<Windows.h>
#include<stdarg.h>
int  average(int n,...)
{
int sum=0;
int i=0;

va_list arg;//arg变量用于访问参数列表的未确定部分,这个变量是一个存储可变参数列表地址的指针,通过这个指针找到参数列表的地址,再结合参数类型,得到参数值

     va_start(arg,n);//通过调用va_start来实现初始化,arg是变量va_list变量的名字,n是省略号前第一个有名字的参数,初始化把arg变量设置为指向可变参数列表的第一个参数
for(i=0; i<n; i++)
{
sum+=va_arg(arg,int);//va_arg接受两个参数,arg变量和参数列表中下一个参数的类型,在有些函数中,可能要通过前面获得的数据来判断下一个参数的类型,va_arg返回这个参数的值,并使var_arg指向下一个可变参数。
}
return sum/n;
va_end(arg);//由于被调函数在调用时不知道参数的正确数目,所以要人为的加上结束条件使函数结束
}
int main()
{
int a=20;
int b=30;
int avg=average(2,a,b);
printf("avg=%d\n",avg);
    system("pause");
return 0;


}

例子二:

//使用可变参数,求函数参数的最大值
#include<stdio.h>
#include<Windows.h>
#include<stdarg.h>
int Max(int n,...)
{
va_list arg;//声明变量访问可变参数列表的未确定部分
int i=0;
int max=0;
va_start(arg,n);//初始化变量指向可变参数列表的第一个参数
max=va_arg(arg,int);
for(i=1;i<n;i++)
{
int  z=va_arg(arg,int);//每次使用va_arg(arg,int)它都指向下一个数字,
//创建临时变量来保存第二个值。
       if(max<z)
   max=z;
}
return max;
va_end(arg);
}
int main()
{
int a=19;
int b=11;
int arg=Max(2,a,b);
printf("Max is %d\n",arg);
system("pause");
return 0;
}

总结:1.参数列表中至少有一个命名参数,确定可变参数列表从哪里开始。如果一个命名参数都没有,就无法使用va_start.

    2.这些宏无法判断实际存在的参数的数量。

    3.这些宏无法判断每个参数的类型。

    4.va_arg如果指定了错误的类型,结果不可预测。因为va_arg无法正确识别作用于可变参数之上的缺省参数提升。当参数列表中可变部分的参数实际传递给函数时,它们将经历缺省参数提升。

    5.可变参数必须从头到尾访问。如果你在访问了几个可变参数之后想半途而废,这是可以的。但是,如果你想一开始被访问参数列表中间的参数,那是不行的。

   6.可变参数的实现过程是使用宏的封装。

   

最后,使用可变参数列表来模拟实现printf函数

//模拟实现printf函数
#include<stdio.h>
#include<Windows.h>
#include<stdarg.h>
#include<assert.h>


void myprintf(int n)
{
int a=n/10;
if(a)
{
myprintf(a);
}
putchar(n%10+'0');
}
void print(char *format,...)
{

va_list arg;
va_start(arg,format);
while(*format)
{
if(*format=='%')
{
format++;
switch(*format)
{

case 's':{
char *str=va_arg(arg,char*);
while(*str)
{
putchar(*str++);
}
*format++;
break;
}
case 'c':{
char ch=va_arg(arg,char);
putchar(ch);
*format++;
break;
}
case 'd': {
int a=va_arg(arg,int);
myprintf(a);
*format++;
break;}
}
}
else 
{
putchar(*format);
*format++;
}
}


va_end(arg);


}


int main()
{
print("s ccc d.\n","hello",'b','i','t',100);
system("pause");
return 0;
}












原创粉丝点击