变长参数

转载自:http://blog.csdn.net/tht2009/article/details/7019635

   变长参数

 设计一个参数个数可变、参数类型不定的函数是可能的,最常见的例子是printf函数、scanf函数和高级语言的Format函数。在C/C++中,为了通知编译器函数的参数个数和类型可变(即是不定的、未知的),就必须以三个点结束该函数的声明。

// printf函数的声明int printf(const char * _Format, ...);//scanf函数声明int scanf(const char * _Format, ...);//自定义变长参数函数func的声明int func(int a,int b,...);


          上面func函数的声明指出该函数至少有两个整型参数和紧随其后的0个或多个类型未知的参数。在C/C++中,任何使用变长参数声明的函数都必须至少有一个指定的参数(又称强制参数),即至少有一个参数的类型是已知的,而不能用三个点省略所有参数的指定,且已知的指定参数必须声明在函数最左端。

int func(...);//错误  int func(...,int a);//错误  

      变长参数函数的实现

       含有变长参数的函数是怎么实现的呢?变长参数函数的实现其实关键在于怎么使用参数,指定了的参数好说,直接使用指定的参数名称访问,但未指定的参数呢?我们知道函数调用过程中参数传递是通过栈来实现的,一般调用都是从右至左的顺序压参数入栈,因此参数与参数之间是相邻的,知道前一个参数的类型及地址,根据后一个参数的类型就可以获取后一个参数的内容。对于变长参数函数,结合一定的条件,我们可以根据最后一个指定参数获取之后的省略参数内容。如,对于函数func,我们知道了参数b的地址及类型,就可知道第一个可变参数的栈地址(如果有的话),如果知道第一个可变参数的类型,就可知道第一个可变参数的内容和第二个可变参数的地址(如果有的话)。以此类推,可以实现对可变参数函数的所有参数的访问。

       那么,要怎么指定上诉的“一定的条件”呢?最简单的方法就像printf等函数一样,使用格式化占位符。分析格式化字符串参数,通过事先定义好的格式化占位符可知可变参数的类型及个数,从而获取各个参数内容。一般对于可变参数类型相同的函数也可直接在强制参数中指定可变参数的个数和类型,这样也能获取各个参数的内容。

       无论哪种,都涉及对栈地址偏移的操作。结合栈存储模式和系统数据类型的字长,我们可根据可变参数的类型很容易得到栈地址的偏移量。这里简单介绍使用va_start、va_arg、va_end三个标准宏来实现栈地址的偏移及获取可变参数内容。这三个宏定义在stdarg.h头文件中,他们可根据预先定义的系统平台自动获取相应平台上各个数据类型的偏移量。

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;  
}  



       对于可变参数函数的调用有一点需要注意,实际的可变参数的个数必须比前面强制参数中指定的个数要多,或者不小于,也即后续参数多一点不要紧,但不能少,如果少了则会访问到函数参数以外的堆栈区域,这可能会把程序搞崩掉。前面强制参数中指定的类型和后面实际参数的类型不匹配也有可能造成程序崩溃。 

 变长参数函数与默认参数函数

 

       拥有变长参数的函数在声明定义时其参数个数与类型是不定的,在运行调用时参数的状态则是一定的。而默认参数函数在声明定义时其参数类型与个数都是一定的,只是后面部分参数指定了默认值,可通过省略(不指定)部分参数调用这个默认参数函数。但是默认参数函数还是使用了声明中指定的全部参数,只不过编译器做了个顺水人情,自动给后部分参数赋了默认值;而变长参数函数则仅仅使用了运行调用时提供的参数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/258945.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第十七章 我国农业科学技术

农村改革解说(专著)第十七章 第十七章 我国农业科学技术 1、为什么说科学技术是生产力? 我们说科学技术是生产力,是因为在构成生产力的两个主要因素中,都包含着科学技术在内。 A、生产力中人的因素是同一定的科学技术紧…

《淘宝网开店 拍摄 修图 设计 装修 实战150招》一一1.2 选购镜头时应注意的事项...

本节书摘来自异步社区出版社《淘宝网开店 拍摄 修图 设计 装修 实战150招》一书中的第1章,第1.2节,作者: 葛存山,更多章节内容可以访问云栖社区“异步社区”公众号查看。 1.2 选购镜头时应注意的事项 面对如此之多的镜头&#xf…

OpenCV中的神器Image Watch

Image Watch是在VS2012上使用的一款OpenCV工具,能够实时显示图像和矩阵Mat的内容,跟Matlab很像,方便程序调试,相当好用。跟VS2012配合使用,简直就是一款神器!让我一下就爱上它了! 下面介绍一些链…

python异步_Python通过Thread实现异步

当long函数耗时较长时,需要程序先向下执行,这就需要异步,改写代码如下: import _thread import time def long(cb): print (long execute) def fun(callback): time.sleep(5) result long end callback(result) _thread.start_ne…

SAM4E单片机之旅——13、LCD之ASF初步

在Atmel Studio 6中,集成了Atmel Software Framework(ASF框架)。通过它提供的库,可以很快速地完成新的项目。 这次的最终目标使用ASF在LCD上显示出文字“Hello World!”,现阶段目标是点亮LCD的背光,学习目标…

《HTML5与CSS3实战指南》——2.2 基本的HTML5模板

本节书摘来自异步社区《HTML5与CSS3实战指南》一书中的第2章,第2.2节,作者: 【美】Estelle Weyl , Louis Lazaris , Alexis Goldstein 更多章节内容可以访问云栖社区“异步社区”公众号查看。 2.2 基本的HTML5模板 在您学习HTML5和新技术时,您…

c# Message const

typeTMsg packed recordhwnd: HWND; //窗口句柄message: UINT;//消息常量标识符wParam: WPARAM ;// 32位消息的特定附加信息lParam: LPARAM ;// 32位消息的特定附加信息time: DWORD;//消息创建时的时间pt: TPoint; //消息创建时的鼠标位置end ; 消息中有什么?是否觉…

OpenCV坐标体系的初步认识

实验基础本次实验通过一个简短的例子,主要来说明下面4个问题: 1. 坐标体系中的零点坐标为图片的左上角,X轴为图像矩形的上面那条水平线;Y轴为图像矩形左边的那条垂直线。该坐标体系在诸如结构体Mat,Rect,Point中都是适用的。&…

python爬取知乎live_Python爬虫 - 简单抓取百度指数

前言有点忙,没空写东西,这是之前写的,加了些配图而已 这次要爬的网站是百度指数 正文 一、分析 打开网站(百度指数),呈现出来是这样的 如果搜索的话就需要登陆了,如果没有什么特别频繁的请求的话,直接登陆复…

在Visual Studio上开发Node.js程序

在Visual Studio上开发Node.js程序 原文:在Visual Studio上开发Node.js程序【题外话】 最近准备用Node.js做些东西,于是找找看能否有Visual Studio上的插件以方便开发。结果还真找到了一个,来自微软的Node.js Tools for Visual Studio(NTVS&a…

Oracle ASM 翻译系列第十一弹:高级知识 Offline or drop?

Offline or drop? 当一个ASM磁盘不可用时,ASM会把它从磁盘组里移除,对吗?要看情况,通常取决于ASM版本和磁盘组的冗余级别。因为一个external冗余的磁盘组会直接被dismount,所以主要关注normal和high冗余磁盘组的情况。…

net与树莓派的情缘-安装与卸载MySql(五)

安装MySql sudo apt-get install mysql-server 删除 mysql sudo apt-get autoremove --purge mysql-server-5.0sudo apt-get remove mysql-serversudo apt-get autoremove mysql-serversudo apt-get remove mysql-common //这个很重要上面的其实有一些是多余的。 清理残留数据 …

mpls工作原理通俗解释_用这两种方法向最终用户解释NLP模型的工作原理还是不错的...

点击上方关注,All in AI中国上周,我看了一个关于“NLP的实践特性工程”的演讲。主要是关于LIME和SHAP在文本分类可解释性方面是如何工作的。我决定写一篇关于它们的文章,因为它们很有趣、易于使用,而且视觉上很吸引人。所有的机器…

向往2的年代

1. JDBC 对插入大量数据如何处理? 2. JAVA反射的使用,如何获取一个java类的某个方法? 3. 数据库连接池(优化) 4. 分布式事务管理转载于:https://www.cnblogs.com/dragonflyyi/p/3564843.html

C++ limits头文件的用法(numeric_limits)

初学C的时候,对这个模板很陌生,不知道它到底是做什么用的,今天拿起《C标准程序库》,出现了它的讨论,所以决定好好研究一番。 1. numeric_limits是什么? (A)《C标准程序库》&#xff…

三层架构——配置文件

1、配置文件是什么? 配置文件是随安装程序一起被安装到计算机上的文件,里面存放着安装好的应用程序执行时所须要的參数。 应用程序配置文件是标准的XML文件,XML标记和属性是区分大写和小写的。它能够按须要更改,开发者可使用配置文…

《嵌入式系统开发之道——菜鸟成长日志与项目经理的私房菜》——02-04项目范围(Scope)管理...

本节书摘来异步社区《嵌入式系统开发之道——菜鸟成长日志与项目经理的私房菜》一书中的第2章,第2.4节,作者:邱毅凌,更多章节内容可以访问云栖社区“异步社区”公众号查看 02-04项目范围(Scope)管理 嵌入式…

flex(入门)之timer的使用,键盘,鼠标的监听

package {import flash.display.Shape;import flash.display.Sprite;import flash.events.Event;import flash.events.KeyboardEvent;import flash.events.MouseEvent;import flash.events.TimerEvent;import flash.utils.Timer;import mx.controls.Label;//窗体大小&#xff0…

python 线程超时设置_python 条件变量Condition(36)

文章首发微信公众号,微信搜索:猿说python对于线程与线程之间的交互我们在前面的文章已经介绍了 python 互斥锁Lock / python事件Event , 今天继续介绍一种线程交互方式 – 线程条件变量Condition.一.线程条件变量Condition相关函数介绍acquire() — 线程…

MsWord 操作总结

转自(http://www.cnblogs.com/eye-like/p/4121219.html) Msdn上的word操作api(不过只有英文版,英文差的先闪过) Word2007的API:http://msdn.microsoft.com/en-us/library/bb257531(voffice.12).aspxWord201…