可变函数
可变参数列表通过宏来实现,定义于stdarg.h头文件,是标准库的一部分。
这个头文件声明了一个类型va_list和三个宏--va_start、va_arg和va_end。
声明一个类型为va_list的变量,与几个宏配合使用,访问参数的值。

函数的使用方法
必须按如下步骤进行:
1.在函数原型中使用省略号。
2.在函数定义中创建一个va_list类型的变量。
3.用宏将该变量初始化为一个参数列表。
4.用宏访问这个参数列表。
5.用宏完成清理工作。

注:这类函数的原型应该具有一个参量列表,参量列表中至少有一个后跟省略号的参量,即:省略号前至少要有一个有名字的参数。

宏的使用
1.va_start初始化va_list变量,宏va_start接受两个参数:va_list变量和省略号前最后一个有名字的参数。
2.通过va_arg访问参数,宏va_arg接受两个参数:va_list变量和参数列表中下一个参数的类型。
注:实际参数类型必须与说明的类型相匹配,如果参数列表中第一个参数为double型,第二个参数为int型,那么va_arg必须做调整。
1 double tic;
2 int toc;
3 
4 tic = va_arg( var_arg, double );
5 toc = va_arg( var_arg, int );
3.va_end:访问完最后一个可变参数后,需要调用va_end,参数:va_list变量。
实例:
average.c

vc下测试:

 1 #include< stdio.h >
 2 #include< stdarg.h >
 3 
 4 void test( char a, char b,  );
 5 
 6 int main( void )
 7 {
 8     char a,b;
 9     b='a';//如果b不初始化,输出垃圾值。
10 
11     test( a, b, 13'd', b, '*' );
12 
13     return 0;
14 }
15 
16 void test( char a, char b,  )
17 {
18     va_list var_arg;
19  
20     va_start( var_arg, a );
21 
22     forint i = 0; i < 8; i++ )
23         printf("%d\n",va_arg( var_arg, int ));
24     
25     va_end( var_arg );
26 }
运行结果:

结果说明:
1.代码第20行va_start宏的第二个参数是a,并不是省略号的前一个参数,
说明:关于va_list第二个参数:不一定是省略号前最后一个有名字参数,在vc下测试时,倒数第二个参数也能正常运行。
2.最后两行输出值为0,可变参数为5个,小于for循环中的循环控制变量;
说明:当访问完最后一个可变参数后,调用va_arg( var_arg, type );的返回值恒为0(vc6.0测试)。

3.当将第11代码test中的 '*'换成一个float类型的变量c = 1.0;在结果中值却是0;是什么原因?
结果如下图:


va_arg()不提供退回前参数的方法,所以保存va_list的副本会是有用的。
c99为此添加了宏va_copy(),接受两个va_list变量,将第二个参数复制到第一个参数中:
1 va_list ap;
2 va_list apcopy;
3 double tic;
4 double toc;
5 
6 va_start( ap, lim );              //把ap初始化为参数列表
7 va_copy( apcopy, ap );        //apcopy是ap的一个副本
8 tic = va_arg( ap, double );    //取得第一个参数
9 toc = va_arg( ap, int );        //取得第二个参数
此时,虽然已从ap中删除了前面两项,但还可以从apcopy中重新获取这两项。
Posted on 2013-07-01 23:14 烽火依然 阅读(296) 评论(0)  编辑 收藏 引用 所属分类: c和指针

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理