一、缘由
之前一直有见识过可变参数,但是没有机会使用,也没理解其背后的机制,今天不如写篇博客,研究研究~
二、情景作业
老师布置作业:
写一个程序:要求得到平均数,且用户可以输入任意数量的参数 要解决该问题有两个难点:
下面几位同学的做法:
2.1 二傻小憨
疯狂地枚举出各种情况,从用户输入1个参数到用户输入100个参数
float average(int a)
{
return a;
}
float average(int a,int b)
{
return (a+b)/2;
}
...........
float average(int a,int b,int c......,int n)
{
return (a+b+c+......n)/2;
}
最终得分:0
2.2 机智源源
#include<stdarg.h>
#include <cstdarg>
#include<iostream>
using namespace std;
float average(int n_values, ...)
{
va_list arg;
int count;
float sum = 0;
/*准备访问可变参数*/
va_start(arg, n_values);
/*添加取自可变参数列表的值*/
for (count = 0; count < n_values; ++count)
{
sum = sum + va_arg(arg, int);
}
/*完成可变参*/
va_end(arg);
return sum / n_values;
}
int main(int n, char**)
{
cout << "平均值是:" <<average(4,10,90,20,80)<< endl;
return 0;
}
得分:100
三、讲解作业
3.1 stdarg
宏
通过此宏可以实现可变参,包含头文件:stdarg .h中,它是标准库的一部分。该头文件包括一个类型三个宏。这几个宏配合使用,访问参数的值。
类型:
va_list
宏:
va_start、va_arg、va_end
3.1 省略号...
省略号:...中,它提示此处可能传递数量和类型未确定的参数。在编写这个函数的原型时,也要使用相同的记法。
3.2 va_list
、va_start
宏
函数声明了一个类型为va_list
名叫 arg
的变量,它用于访问参数列表的未确定部分。这个变量通过调用var_start
来初始化。初始化过程把arg
变量设置为指向可变参数部分的第1个参数。
var_start([va_list类型的名字],[省略号前最后一个有名字的参数])
3.3 va_arg
宏、va_end
宏
为了访问参数,需要使用va_arg
,这个宏接受两个参数:
va_arg([va_list类型参数],参数列表中下一个参数)
当访问完毕最后一个可变参数之后,我们需要调用va_end
。
## 3.4
__VA_ARGS__
宏
cpp #define debug(...) print(cout,__VA_ARGS__) #define debug2(os, ...) print(os, __VA_ARGS__) //#define debug2(format, args...) print(format, ##args)//win32不支持 debug2(cout,"this ", " year");//"this year"
# 四、总结
| 用法总结|
|:--|
|
va_list ptr
: 定义一个指向可变参数列表的指针
va_start(ptr,a)
:初始化指针,其中第二个参数为函数可变参数列表之前的固定参数
va_arg(ptr,int)
:取出指针指向的元素,第二个参数为元素的类型,返回值为取出的元素,同时指针后移。
va_end(ptr)
: 还原
ptr
指针 |
# 五、可变参数的限制
注意: 可变参数必须从头到尾按照顺序逐个访问。
如果你在访问了几个可变参数后想半途中止,这是可以的。但是,如果你想一开始就访问参数列表中间的参数,那是不行的。
由于表中的可变参数部分并没有原型,所以,所有作为可变参数传递给函数的值都将执行缺省参数类型提升。