免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1299 | 回复: 0
打印 上一主题 下一主题

[iOS] Objective-C可变参数的函数实现 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-06-16 09:15 |只看该作者 |倒序浏览
1.前言
相信接触过OC的对NSLog都很熟悉,细心查看NSLog的原始定义,会发现,他的原型如下:

FOUNDATION_EXPORT void NSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2);
路径在:OS X version/Frameworks/Foundation/NSObjCRuntime.h

注意到参数最后的...,这里是可变参数。这样,在调用时就可以根据需要传入相应个数的参数了。

PS:其实在C#中也有params指定可变参数,跟OC这个很类似。

那么,如何在自己写的函数中实现可变参数呢?

2.实现
要实现OC中的可变参数,需要几个宏定义va_list、va_start、va_arg、va_end,先实现效果,以无限个整数相加为例:

RandomArgs.h
  1. #import <Foundation/Foundation.h>

  2. @interface RandomArgs : NSObject
  3. -(int)add:(int)item,...;
  4. @end
  5. RandomArgs.m

  6. #import "RandomArgs.h"

  7. @implementation RandomArgs
  8. -(int)add:(int)item,...{
  9.     va_list list;
  10.     va_start(list, item);

  11.     int result=0;
  12.      NSLog(@"第一个参数:%d",item);
  13.     result+=item;
  14.     int arg;
  15.     while ((arg=va_arg(list,int))) {
  16.          NSLog(@"当前参数:%d",arg);
  17.         result+=arg;
  18.     }
  19.     va_end(list);
  20.     return result;
  21. }
  22. @end
  23. main.m

  24. #import <Foundation/Foundation.h>
  25. #import "RandomArgs.h"

  26. int main(int argc, const char * argv[]) {
  27.     @autoreleasepool {
  28.         RandomArgs* rand=[[RandomArgs alloc]init];
  29.         int result=[rand add:4,5,6,nil];
  30.         NSLog(@"结果:%d",result);

  31.     }
  32.     return 0;
  33. }
复制代码
效果

3.总结
主要是通过循环va_arg来获取,但是要注意的是,第一个参数必须是固定的,循环里面只能获取第二个参数以后的参数。

4.原理
参数在堆栈中分布,位置

在进程中,堆栈地址是从高到低分配的.当执行一个函数的时候,将参数列表入栈,压入堆栈的高地址部分,然后入栈函数的返回地址,接着入栈函数的执行代码,这个入栈过程,堆栈地址不断递减,一些黑客就是在堆栈中修改函数返回地址,执行自己的代码来达到执行自己插入的代码段的目的。

总之,函数在堆栈中的分布情况是:地址从高到低,依次是:函数参数列表,函数返回地址,函数执行代码段。

堆栈中,各个函数的分布情况是倒序的.即最后一个参数在列表中地址最高部分,第一个参数在列表地址的最低部分.参数在堆栈中的分布情况如下:

最后一个参数

倒数第二个参数

...

第一个参数

函数返回地址

函数代码段
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP