- 1、本文档共13页,可阅读全部内容。
- 2、有哪些信誉好的足球投注网站(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
如何实现参数个数可变的函数
参数个数不定的函数,最频繁使用的就是printf()与scanf()。其实,我们也可以自己实现这样的功能,首先看一个例子:
#include stdio.h
#include stdarg.h
int Sum(int first, int second, ...)
{
????? int sum = 0, t = first;
????? va_list vl;
????? va_start(vl, first);
????? while (t != -1)
????? {
???????????? sum += t;
???????????? t = va_arg(vl, int);//将当前参数转换为int类型
????? }
????? va_end(vl);
????? return sum;
}
int main(int argc, char* argv[])
{
????? printf(The sum is %d\n, Sum(30, 20, 10, -1));//-1是参数结束标志
????? return 0;
}
在上面的例子中,实现了一个参数个数不定的求int型和的函数Sum()。函数中一开始定义了一个va_list型变量vl,该变量用来访问可变参数,实际上就是指针,接着使用va_start使vl指向第一个参数,然后再使用va_arg来遍历每一个参数,va_arg返回参数列表中的当前参数并使vl指向参数列表中的下一个参数。最后通过va_end把vl指针清为NULL。在这里,va_start,va_arg,va_end其实都是宏,那么这些宏又是如何实现他们的功能的呢?
一 个很显然的问题就是既然参数个数在函数调用之前没有确定,所以,在函数定义的时候没有办法像普通函数那样使用确定的变量来接受传进来的参数,于是,问题的 关键就是如何接收到这些不确定的参数了?首先,看看函数调用时实际发生的情况,在函数调用的时候,使用栈传递参数,拿上例来说,如果调用Sum(30, 20, 10, -1),那么参数入栈后的情形如下图所示(假定按照自右至左的顺序入栈):
既然参数在栈中的情形已经知道了,那么,如果使用指针(程序中的
vl)指向第一个参数(va_start(vl, first)),因为所有参数都是连续存放的,通过移动指针就可以访问到每一个参数了(va_arg(vl, int)),这就是我在程序中使用到那几个宏的实现思想。
?????? 明白了以上原理之后,就可以完全不使用宏,自己实现这样的一个功能了,下面的程序是我按照上面的思想改写的:
#include stdio.h
int Sum(int first, int second, ...)
{
int sum = 0, t = first;
char * vl;//定义一个指针
vl = (char *)first;//使指针指向第一个参数
while (*vl != -1)//-1是预先给定的结束符
{
??????? sum += *(int *)vl;//类型转换
??????? vl += sizeof(int);//移动指针,使指针指向下一个参数
}
return sum;
}
int main(int argc, char* argv[])
{
printf(The sum is %d\n, Sum(30, 20, 10, -1));//-1是参数结束标志
return 0;
}
可以看出,通过使用指针的确实现了参数个数不定的函数了,但是程序中还有一个问题,那就是移动指针,在程序中因为我使用的参数都是相同的int类型,所以可以事先知道访问下一个参数的时候应该移动sizeof(int)个字节,但是,如果参数的类型不同呢?这的确是个比较麻烦的问题,因为不同的数据类型占用的字节数可能是不一样的(如double型为8个字符,short int型为2个),所以很难事先确定应该移动多少个字节!但是办法还是有的,这就是使用指针了,无论什么类型的指针,都是占用4个字节,所以,可以把所有的传人参数都设置为指针,这样一来,就可以通过移动固定的4个字节来实现遍历可变参数的目的了,至于如果取得指针中的内容并使用他们,当然也是无法预先得知的了,所以这大概也就是像printf(),scanf()之类的函数还需要一个格式控制符的原因吧^_^!不过实现起来还是有不少麻烦,暂且盗用vprintf()来实现一个与printf()函数一样功能的函数了,代码如下:
void myPrint(const char *frm, ...)
{
??? va_list vl;
??? va_start(vl, frm);
??? vprintf(frm, vl);
???
您可能关注的文档
- 如何培养好的写字习惯.doc
- 如何培养学困生的良好学习习惯.doc
- 如何培养学生分析及解决物理问题的能力.doc
- 如何培养学生正确的书写王娥.doc
- 如何培养学生的交往能力.doc
- 如何培养学生的古文语感.doc
- 如何培养学生的意志力.doc
- 如何培养学生的注意力.doc
- 如何培养学生的符号运算能力.doc
- 如何培养学生自主学习的习惯.doc
- 25上半年2期套题班-行政职业能力测验(八).docx
- 公考讲义-2025年1月时政汇总.pdf
- 2025年省考逻辑填空1000 高频实词积累+刷题早读课 讲义.pdf
- 25上半年2期套题班-行政职业能力测验(九).docx
- 2025四川事业编FB综合岗考试-综合能力测试讲义-主观题基础,案例分析题,公文写作及文章写作题.pdf
- 25上半年2期套题班-行政职业能力测验(五).docx
- 2025申论多省联考刷题课真题资料-2025国考执法课程.doc
- 2025申论多省联考刷题课真题资料-2024江西执法课程.doc
- 25上半年2期套题班-行政职业能力测验(十).docx
- 2025申论多省联考刷题课真题资料-2024福建县乡课程.doc
文档评论(0)