首页 > 代码库 > 可变参数函数
可变参数函数
http://blog.csdn.net/ithzhang/article/details/7021317
变长参数的函数即参数个数可变、参数类型不定 的函数。
最常见的例子是printf函数、scanf函数和高级语言的Format函数。在C/C++中,为了通知编译器函数的参数个数和类型可变(即是不定的、未知的),就必须以三个点结束该函数的声明。
// printf函数的声明int printf(const char * _Format, ...);//scanf函数声明int scanf(const char * _Format, ...);//自定义变长参数函数func的声明int func(int a,int b,...);
在C/C++中,任何使用变长参数声明的函数都必须至少有一个指定的参数(又称强制参数),即至少有一个参数的类型是已知的,而不能用三个点省略所有参数的指定,且已知的指定参数必须声明在函数最左端
//下面这种声明是非法的 int func(...);//错误 int func(...,int a);//错误
- 因为C语言压栈顺序为从右到左。
- 栈的扩展方向是向下扩展,所以栈底为高地址,栈顶为低地址。
比如假设f(a,b,c,d)按照从右到左压栈,那么d应该是第一个进栈的,a是最后一个进栈的,所以d的地址应该比a的高。所以通过递增地址的办法可以得到下一个参数、、
因此参数与参数之间是相邻的,知道前一个参数的类型及地址,根据后一个参数的类型就可以获取后一个参数的内容
//访问可变参数流程 va_list args; //定义一个可变参数列表 va_start(args,arg);//初始化args指向强制参数arg的下一个参数; va_arg(args,type);//获取当前参数内容并将args指向下一个参数 ...//循环获取所有可变参数内容 va_end(args);//释放args
//sum为求和函数,其参数类型都为int,但参数个数不定 //第一个参数(强制参数)n指定后面有多少可变参数 int sum(unsigned int n,...) { int sum=0; va_list args; va_start(args,n); while(n>0) { //通过va_arg(args,int)依次获取参数的值 sum+=va_arg(args,int); n--; } va_end(args); return sum; }
上面这段代码经测试可以正常输出。也就是说,我们通过使用指针,实现了参数不定的函数。但这里还有一个问题,就是sum函数的所有参数都是int类型的,事先我们知道要移动sizeof(int)位的指针,可是如果参数类型不同呢?
答案与分析:这的确是个比较麻烦的问题,因为不同的数据类型占用的字节数可能是不一样的(如double型为8个字符,short int型为2个),所以很难事先确定应该移动多少个字节!但是办法还是有的,这就是使用指针了,无论什么类型的指针,都是占用4个字节,所以,可以把所有的传如入参数都设置为指针,这样一来,就可以通过移动固定的4个字节来实现遍历可变参数的目的了,至于如何取得指针中的内容并使用他们,当然也是无法预先得知的了。所以这大概也就是像printf(),scanf()之类的函数还需要一个格式控制符的原因吧
可变参数函数