首页 > 代码库 > 可变参数函数

可变参数函数

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);//错误  

  

  1. 因为C语言压栈顺序为从右到左。
  2. 栈的扩展方向是向下扩展,所以栈底为高地址,栈顶为低地址。

    比如假设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()之类的函数还需要一个格式控制符的原因吧

可变参数函数