可变长度函数参数的原理及使用

可变长度函数参数的原理及使用

ID:41585344

大小:55.93 KB

页数:7页

时间:2019-08-28

可变长度函数参数的原理及使用_第1页
可变长度函数参数的原理及使用_第2页
可变长度函数参数的原理及使用_第3页
可变长度函数参数的原理及使用_第4页
可变长度函数参数的原理及使用_第5页
资源描述:

《可变长度函数参数的原理及使用》由会员上传分享,免费在线阅读,更多相关内容在工程资料-天天文库

1、可变长度函数参数的原理及使用概述由于在C语言中没有函数重载,解决不定数H函数参数问题变得比较麻烦;即使采用C++,如果参数个数不能确定,也很难采用函数重载•对这种情况,有些人采用指针参数来解决问题。卜•面就c语言屮处理不定参数数目的问题进行讨论。定义大家先看几宏.在VC++6.0的include有一个stdarg.h头文件,有如下几个宏定义:#defineJNTSIZEOF(n)((sizeof(n)+sizeof(int)-1)&~(sizeof(int)・1))#defineva_start(ap,v)(ap=(vajist)&v+」NTSIZEOF(

2、v))//第一个可选参数地址#defineva_arg(ap,t)(*(t*)((ap+=_INTSIZEOF(t))-JNTSIZEOF(t)))〃下一个参数地址#defineva_end(ap)(ap=(vaJist)O)//将指针置为无效如果对以上几个宏定义不理解,可以略过,接这看后面的内容。参数在堆栈中分布,位置在进程中,堆栈地址是从高到低分配的•当执行一个函数的时候,将参数列表入栈,压入堆栈的高地址部分,然后入栈函数的返回地址,接着入栈函数的执行代码,这个入栈过程,堆栈地址不断递减,一些黑客就是在堆栈中修改函数返回地址,执行自己的代码来达到执行自

3、己插入的代码段的日的•总之,函数在堆栈小的分布情况是:地址从高到低,依次是:函数参数列表,函数返回地址,函数执行代码段。堆栈中,各个函数的分布情况是倒序的。即最后一个参数在列表中地址最高部分,第一个参数在列表地址的最低部分•参数在堆栈中的分布情况如下:最后一个参数倒数第二个参数■•■笫一个参数函数返回地址函数代码段示例代码voidarg_test(inti,...);intmain(intargc,char*argv[]){intint_size=JNTSIZEOF(int);printf(,,int_size=%d,,Jint_size);arg_t

4、est(0,4);arg_cnt(4,1,2,3,4);return0;}voidarg_test(inti,...){intj=0;vajistarg_ptr;va_start(arg_ptr,i);printf(”&i=%p",&);//打印参数i在堆栈中的地址printf(narg_ptr=%p",arg_ptr);〃打印va_start之后arg_ptr地址,〃应该比参数i的地址高sizeof(int)个字节〃这时arg_ptr指向下一个参数的地址j=*((int*)arg_ptr);printf(n%d%dH,i,j);j=va_ar

5、g(arg_ptr,int);printf(”arg_ptr=%p”,arg_ptr):〃打印va_arg后arg_ptr的地址〃应该比调用va_arg前高sizeof(int)个字节〃这时arg_ptr指向下一个参数的地址va_end(arg_ptr);printf(n%d%dH,i,j);}代码说明:intint_size=JNTSIZEOF(int);M至Uint类型所占字节数va_start(arg_ptr,i);得到第一个可变参数地址,根据定义(va_list)&v得到起始参数的地址,再加上」NTSIZEOF(v),就是其实参数下一个参数

6、的地址,即第一个可变参数地址.j=va_arg(arg_ptr,int);得到第一个参参数的值,并且arg_ptr指针上移一个_INTSIZEOF(int),即指向下一个可变参数的地址.va_end(arg_ptr);置空arg_ptr,B卩arg_ptr=O;总结:读取可变参数的过程其实就是堆栈中,使用指针,遍历堆栈段中的参数列表,从低地址到高地址一个一个地把参数内容读出来的过稈.在编程中应该注意的问题和解决办法虽然可以通过在堆栈中遍历参数列表來读出所有的可变参数,但是由于不知道可变参数有多少个,什么时候应该结束遍历,如果在堆栈中遍历太多,那么很可能读取

7、一些无效的数据.解决办法a可以在第一个起始参数中指定参数个数,那么就可以在循环还中读取所有的可变参数;b・定义一个结束标记,在调用函数的时候,在最后一个参数屮传递这个标记,这样在遍历可变参数的时候,可以根据这个标记结束可变参数的遍历;下面是一段示例代码:〃第一个参数定义可选参数个数,用于循环取初参数内容voidarg_cnt(intcnt,...);intmain(intargc,char*argv[]){intint_size=JNTSIZEOF(int);printf(nint_size=%dH,int_size);arg_cnt(4,1,2,3,

8、4);return0;}voidarg_cnt(intent,..

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

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

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