如何在C语言中实现参数个数不确定的函数.pdf

如何在C语言中实现参数个数不确定的函数.pdf

ID:51489992

大小:95.95 KB

页数:5页

时间:2020-03-25

如何在C语言中实现参数个数不确定的函数.pdf_第1页
如何在C语言中实现参数个数不确定的函数.pdf_第2页
如何在C语言中实现参数个数不确定的函数.pdf_第3页
如何在C语言中实现参数个数不确定的函数.pdf_第4页
如何在C语言中实现参数个数不确定的函数.pdf_第5页
资源描述:

《如何在C语言中实现参数个数不确定的函数.pdf》由会员上传分享,免费在线阅读,更多相关内容在行业资料-天天文库

1、如何在C语言中实现参数个数不确定的函数?C语言中有一种长度不确定的参数,形如:"...",它主要用在参数个数不确定的函数中,我们最容易想到的例子是printf函数。(注意:在C++中有函数重载(overload)可以用来区别不同函数参数的调用,但它还是不能表示任意数量的函数参数。)C语言用va_start等宏来处理这些可变参数。这些宏看起来很复杂,其实原理挺简单,就是根据参数入栈的特点从最靠近第一个可变参数的固定参数开始,依次获取每个可变参数的地址。在标准C语言中定义了一个头文件专门用来对付可变参数列表,它包含了一组宏,和一个va_list的typedef声明。针对不同平台

2、有不同的宏定义,我们选取X86平台下的宏定义:typedefchar*va_list;#define_INTSIZEOF(n)((sizeof(n)+sizeof(int)-1)&~(sizeof(int)-1))#defineva_start(ap,v)(ap=(va_list)&v+_INTSIZEOF(v))#defineva_arg(ap,t)(*(t*)((ap+=_INTSIZEOF(t))-_INTSIZEOF(t)))#defineva_end(ap)(ap=(va_list)0)//或者简化为typedefchar*va_list;#defineva_start(list)l

3、ist=(char*)&va_alist#defineva_end(list)#defineva_arg(list,mode)((mode*)(list+=sizeof(mode)))[-1]其中说明如下:_INTSIZEOF(n)宏是为了考虑那些内存地址需要对齐的系统<从此可以看出编译器生成参数调用时,必须是满足一定的对齐规则的>.为了能从固定参数依次得到每个可变参数,va_start,va_arg充分利用下面两点:1.C语言在函数调用时,先将最后一个参数压入栈2.X86平台下的内存分配顺序是从高地址内存到低地址内存高位地址第N个可

4、变参数第N-1个可变参数......第二个可变参数第一个可变参数ap固定参数v低位地址由上图可见,&v是固定参数在内存中的地址,在调用va_start后,ap指向第一个可变参数。这个宏的作用就是在v的内存地址上增加v所占的内存大小,这样就得到了第一个可变参数的地址。接下来,可以这样设想,如果我能确定这个可变参数的类型,那么我就知道了它占用了多少内存,依葫芦画瓢,我就能得到下一个可变参数的地址。让我们再来看看va_arg,它先ap指向下一个可变参数,然后减去当前可变参数的大小即得到当前可变参数的内存地址,再做个类型转换,返回它的值。要确定每个可变参数的类型,有两种做法,要么都是默认的类型,要么就

5、在固定参数中包含足够的信息让程序可以确定每个可变参数的类型。比如,printf,程序通过分析format字符串就可以确定每个可变参数大类型。最后一个宏就简单了,va_end使得ap不再指向有效的内存地址。其实在varargs.h头文件中定义了UNIXSystemV实行的va系列宏,而上面在stdarg.h头文件中定义的是ANSIC形式的宏,这两种宏是不兼容的,一般说来,我们应该使用ANSIC形式的va宏。从而总的使用原则是:1)首先在函数里定义一个va_list型的变量,这里是arg_ptr,这个变量是指向参数的指针.2)然后用va_start宏初始化变量arg_ptr,这个宏的第二个参数是第

6、一个可变参数的前一个参数,是一个固定的参数.3)然后用va_arg返回可变的参数,并赋值给整数j.va_arg的第二个参数是你要返回的参数的类型,这里是int型.4)最后用va_end宏结束可变参数的获取.然后你就可以在函数里使用第二个参数了.如果函数有多个可变参数的,依次调用va_arg获取各个参数.5)、标准C库的中的三个宏的作用只是用来确定可变参数列表中每个参数的内存地址,编译器是不知道参数的实际数目的。6)、在实际应用的代码中,程序员必须自己考虑确定参数数目的办法,如a)在固定参数中设标志--printf函数就是用这个办法。b)在预先设定一个特殊的结束标记,就是说多输入一个可变参数,调

7、用时要将最后一个可变参数的值设置成这个特殊的值,在函数体中根据这个值判断是否达到参数的结尾。本文前面的代码就是采用这个办法.无论采用哪种办法,程序员都应该在文档中告诉调用者自己的约定。7)、实现可变参数的要点就是想办法取得每个参数的地址,取得地址的办法由以下几个因素决定:a)函数栈的生长方向b)参数的入栈顺序c)CPU的对齐方式d)内存地址的表达方式8)取得地址后,再结合参数的类型,程序员就可以正

当前文档最多预览五页,下载文档查看全文

此文档下载收益归作者所有

当前文档最多预览五页,下载文档查看全文
温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,天天文库负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。