【C++基础之二十】可变参数的函数

来源:互联网 发布:无间道1细节知乎 编辑:程序博客网 时间:2024/06/04 17:47

原创作品,转载请标明http://blog.csdn.net/jackystudio/article/details/17523523


C++中可变参数的函数是从C中继承而来,可变参数的函数是指函数的参数个数可变,参数类型不定的函数。我们最常见的就是printf()。


1.可变参数函数实现原理

指定参数的函数实现很简单,通过通过指定的参数名访问就行了。但是如果不指定的呢?函数的调用的参数会进行压栈处理,详细可见此文函数调用机制。而对参数的压栈是从右到左进行压栈。而参数和参数之间存放是连续的,也就是说,只要知道第一个参数的地址和类型,以及其他参数的类型,就可以获取各个参数的地址。

比如:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. int printf(const char* format, ...)  

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. printf("%d and % c",a,b);  
这里的a是int型,b是char型。printf()有3个参数,一个const char*,一个是int,一个是char。所以参数压栈的顺序就是先将b入栈,再将a入栈,最后是format入栈,由于栈是向下低地址)生长的,所以在知道了format的地址之后,所有的参数地址都可以计算出来。函数调用内存结构如下:



2.声明和定义

可变参数函数的声明很简单,对于不定参数部分用“...”表示即可。但是实现原理可以看到,第一个的参数的地址是必须提供的,也就是可变参数必须至少包含一个参数,这个参数用来寻址,实现对所有参数的访问。所以像下面这样的声明是错误的。

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. void func(...);  
或者
[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. void func(...,int a);  

当然通常也会在对第一个参数进行一些特殊处理以方便函数的实现,比如强制指定为参数个数,或者像printf一样使用格式占位符来。


3.处理可变参数的标准宏

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //可变参数标准宏头文件  
  2. #include "stdarg.h"  
  3.   
  4. //申明va_list数据类型变量pvar,该变量访问变长参数列表中的参数。  
  5. va_list pvar;  
  6.   
  7. //宏va_start初始化变长参数列表。pvar是va_list型变量,记载列表中的参数信息。  
  8. //parmN是省略号"..."前的一个参数名,va_start根据此参数,判断参数列表的起始位置。  
  9. va_start(pvar, parmN);  
  10.   
  11. //获取变长参数列表中参数的值。pvar是va_list型变量,type为参数值的类型,也是宏va_arg返回数值的类型。  
  12. //宏va_arg执行完毕后自动更改对象pvar,将其指向下一个参数。  
  13. va_arg(pvar, type);  
  14.   
  15. //关闭本次对变长参数列表的访问。  
  16. va_end(pvar);  

4.可变参数函数模版

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #include <stdarg.h>  
  2. function (parmN, ...)  
  3. {  
  4.   
  5.     va_list pvar;   
  6.     va_start (pvar, parmN);  
  7.     while(...)  
  8.     {  
  9.         ...  
  10.             f = va_arg (pvar, type);  
  11.         ...  
  12.     }  
  13.     va_end (pvar);  
  14. }  

5.示例

第一个参数指定了要计算的值的个数。

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #include "stdarg.h"  
  2. using namespace std;  
  3.   
  4. int sum(int count, ...)  
  5. {  
  6.     int sum_value=0;  
  7.   
  8.     va_list args;  
  9.     va_start(args,count);  
  10.     while(count--)  
  11.     {  
  12.         sum_value+=va_arg(args,int);  
  13.     }  
  14.     va_end(args);  
  15.   
  16.     return sum_value;  
  17. }  
  18.   
  19. int _tmain(int argc, _TCHAR* argv[])  
  20. {  
  21.     cout<<sum(5,1,2,3,4,5);//输出15  
  22. }  
0 0
原创粉丝点击