C语言中可变参数函数实现原理浅谈.doc

C语言中可变参数函数实现原理浅谈.doc

ID:61766535

大小:68.50 KB

页数:7页

时间:2021-03-19

C语言中可变参数函数实现原理浅谈.doc_第1页
C语言中可变参数函数实现原理浅谈.doc_第2页
C语言中可变参数函数实现原理浅谈.doc_第3页
C语言中可变参数函数实现原理浅谈.doc_第4页
C语言中可变参数函数实现原理浅谈.doc_第5页
资源描述:

《C语言中可变参数函数实现原理浅谈.doc》由会员上传分享,免费在线阅读,更多相关内容在教育资源-天天文库

1、C语言中可变参数函数实现原理浅析1、C函数调用的栈结构 可变参数函数的实现与函数调用的栈结构密切相关,正常情况下C的函数参数入栈规则为__stdcall,它是从右到左的,即函数中的最右边的参数最先入栈。例如,对于函数:voidfun(inta,intb,intc){intd;...}其栈结构为0x1ffc-->d0x2000-->a0x2004-->b0x2008-->c  对于任何编译器,每个栈单元的大小都是sizeof(int),而函数的每个参数都至少要占一个栈单元大小,如函数voidfun1(chara,intb,doublec,shortd)对一个32的

2、系统其栈的结构就是0x1ffc-->a(4字节)(为了字对齐)0x2000-->b(4字节)0x2004-->c(8字节)0x200c-->d(4字节)因此,函数的所有参数是存储在线性连续的栈空间中的,基于这种存储结构,这样就可以从可变参数函数中必须有的第一个普通参数来寻址后续的所有可变参数的类型及其值。2.C语言通过几个宏来实现变参的寻址根据函数调用的栈结构,标准C语言中,一般在stdarg.h头文件定义了下面的几个宏,用于实现变参的寻址及可变函数的设计,其中有可能不同的商业编译器的发行时实现的具体代码可能不一样,但是原理都是一样的。//Linux2.18内核

3、typedefchar*va_list;/*Storagealignmentproperties--堆栈按机器字对齐其中acpi_native_int是一个机器字,32位机的定义是:typedefu32acpi_native_int*/#define_AUPBND(sizeof(acpi_native_int)-1)#define_ADNBND(sizeof(acpi_native_int)-1)/*Variableargumentlistmacrodefinitions--变参函数内部实现需要用到的宏*/#define_bnd(X,bnd)(((sizeof(

4、X))+(bnd))&(~(bnd)))#defineva_start(ap,A)(void)((ap)=(((char*)&(A))+(_bnd(A,_AUPBND))))#defineva_arg(ap,T)(*(T*)(((ap)+=(_bnd(T,_AUPBND)))-(_bnd(T,_ADNBND))))#defineva_end(ap)(void)0在X8632位机器中,以上这几个宏的用途主要是:C语言传递参数是与__stdcall相同的,C语言传递参数时是用push指令从右到左将参数逐个压栈,因此C语言里通过栈指针来访问参数。虽然X86的push一

5、次可以压2,4或8个字节入栈,C语言在压参数入栈时仍然是机器字的size为最小单位的,也就是说参数的地址都是字对齐的,这就是_bnd(X,bnd)存在的原因。汇编和C,编译出的X86函数一般在进入函数体后立即执行pushebpmovebp,esp这两条指令。首先把ebp入栈,然后将当前栈指针赋给ebp,以后访问栈里的参数都使用ebp作为基指针。下面将对上面几个主要的宏进行分析:①#define_bnd(X,bnd)(((sizeof(X))+(bnd))&(~(bnd)))计算类型为X的参数在栈中占据的字节数,是字对齐后的字节数。acpi_native_unit

6、是一个机器字,32位机的定义是:typedefu32acpi_native_uint;显然,_AUPBND,_ADNBND的值是4-1==3==0x00000003,按位取反(~(bnd))就是0xfffffffc。因此,_bnd(X,bnd)宏在32位机下是((sizeof(X)+3)&0xfffffffc)与&0xfffffffc相与后,最后两位是00,很明显,其作用是实现字对齐。②#defineva_start(ap,A)(void)((ap)=(((char*)&(A))+(_bnd(A,_AUPBND))))va_start(ap,A),初始化参数指针

7、ap,将函数参数A右边第一个参数的地址赋给ap。A必须是一个参数的指针,所以此种类型函数至少要有一个普通的参数。如下图所示:高地址

8、-----------------------------

9、

10、函数返回地址

11、

12、-----------------------------

13、

14、…

15、

16、-----------------------------

17、

18、第n个参数(第一个可变参数)

19、

20、-----------------------------

21、<--va_start后ap指向

22、第n-1个参数(最后一个固定参数)

23、低地址

24、-----------------------------

25、

26、<--&A③#defi

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

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

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