C++ 变长参数函数小结

来源:互联网 发布:建筑动画制作软件 编辑:程序博客网 时间:2024/05/21 18:34
        变长参数的函数,即参数个数可变、参数类型不定的函数设计一个参数个数可变、参数类型不定的函数是可能的,最常见的例子是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++中,任何使用变长参数声明的函数都必须至少有一个指定的参数(又称强制参数),即至少有一个参数的类型是已知的,而不能用三个点省略所有参数的指定,且已知的指定参数必须声明在函数最左端。

变长参数函数的实现
        含有变长参数的函数是怎么实现的呢?变长参数函数的实现其实关键在于怎么使用参数,指定了的参数好说,直接使用指定的参数名称访问,但未指定的参数呢?我们知道函数调用过程中参数传递是通过栈来实现的,一般调用都是从右至左的顺序压参数入栈,因此参数与参数之间是相邻的,知道前一个参数的类型及地址,根据后一个参数的类型就可以获取后一个参数的内容。对于变长参数函数,结合一定的条件,我们可以根据最后一个指定参数获取之后的省略参数内容。如,对于函数func,我们知道了参数b的地址及类型,就可知道第一个可变参数的栈地址(如果有的话),如果知道第一个可变参数的类型,就可知道第一个可变参数的内容和第二个可变参数的地址(如果有的话)。以此类推,可以实现对可变参数函数的所有参数的访问。
        那么,要怎么指定上诉的“一定的条件”呢?最简单的方法就像printf等函数一样,使用格式化占位符。分析格式化字符串参数,通过事先定义好的格式化占位符可知可变参数的类型及个数,从而获取各个参数内容。一般对于可变参数类型相同的函数也可直接在强制参数中指定可变参数的个数和类型,这样也能获取各个参数的内容。
        无论哪种,都涉及对栈地址偏移的操作。结合栈存储模式和系统数据类型的字长,我们可根据可变参数的类型很容易得到栈地址的偏移量。

变长参数函数的简单运用:

// va_arg_test.cpp : 定义控制台应用程序的入口点。////访问可变参数流程//va_list args;//定义一个可变参数列表//va_start(args,arg);//初始化args指向强制参数arg的下一个参数//va_arg(args,type);//获取当前参数内容并将args指向下一个参数//...//循环获取所有可变参数内容//va_end(args);//释放args#include "stdafx.h"#include <stdarg.h>#include <string>#include <vector>/// @brief利用变长参数函数进行求和运算/// @param[in]n : 指定后面有多少可变参数///@remark第一个参数为强制参数///@return得到求和结果double sum(unsigned int n, ...){double sum = 0;va_list args = NULL;//定义一个可变参数列表va_start(args, n);//初始化args指向强制参数arg的下一个参数while(n > 0){//通过va_arg(args, double)依次获取参数的值sum += va_arg(args, double);n--;}va_end(args);//释放argsreturn sum;}/// @brief利用变长参数函数格式化字符串/// @param[in]format : 类似printf中第一个参数///@remark///@return格式化后的字符串std::string format(const char* format, ...){std::string var_str;va_listap;va_start(ap, format);int len = _vscprintf(format, ap);if (len > 0){std::vector<char> buf(len + 1);vsprintf(&buf.front(), format, ap);var_str.assign(buf.begin(), buf.end() - 1);}va_end(ap);return var_str;}//int _tmain(int argc, _TCHAR* argv[]){//求和double cnt = sum(6, 1.1, 2.2, 3.3, 4.4, 5.5, 6.6);printf("sum: %f\n", cnt);//格式化字符串std::string szTmp = format("%s,%s,%s", "this", "is", "kandy");printf("%s \n", szTmp.c_str());system("pause");return 0;}

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



0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 刚开的店没人怎么办 刚开业的店没人怎么办 美容店没人进店怎么办 新店开业招不到营业员怎么办 无意开通了花呗怎么办? 花呗灰色用不了怎么办 花呗逾期用不了怎么办 店铺花呗关闭了怎么办 花呗无法使用了怎么办 借呗自动关闭了怎么办 蚂蚁花呗无法开通怎么办 花呗本月还不了怎么办 蚂蚁借呗没钱还怎么办 淘宝账号被限制登录怎么办 辱骂买家被投诉骚扰怎么办 淘宝卖家骚扰买家怎么办 被淘宝卖家电话骚扰怎么办 闲鱼卖东西买家退货运费怎么办 淘宝被恶意拍单怎么办 炒作信用度评价被删除怎么办 删除淘宝评价之后卖家不返现怎么办 美团客户给差评怎么办 淘宝卖家评价差怎么办 淘宝卖家发货未揽收怎么办 周不过5我超过了怎么办 淘宝申请退款后卖家不确认怎么办 淘宝直通车b类扣12分怎么办 淘宝店铺被买家投诉怎么办 淘宝店铺遭买家投诉怎么办 淘宝店铺被买家恶意投诉怎么办 苹果手机无法识别指纹怎么办 淘宝店铺虚假交易违规怎么办 斗鱼直播太卡怎么办 神笔添加视频尺码不符合怎么办 闲鱼卖家单号填错了怎么办 户户通没有信号强度怎么办 全民k歌qq登不上怎么办 手机直播没电了怎么办 淘宝退货卖家拒收怎么办 充的会员卡店家关门了怎么办 淘宝手机号码被注册了怎么办