现在的位置: 首页 > 综合 > 正文

iOS的结构体存储内存探究

2017年12月08日 ⁄ 综合 ⁄ 共 1735字 ⁄ 字号 评论关闭

http://iostrack.com/post/2012-07-20/40029966662

1、首先定义

typedef struct intStruct

{

 int i;

}intStruct;

然后发现

       intStruct ii={10};

       int i = 10;

在内存的存储都是一样的:0A 00 00 00(原文写的是00 00 00 0A,此处实测结果与原文不服)

由此推断:

如果我们定义的结构体更为复杂,有多个变量,那么它们在内存中是依次排列的(不考虑大端小端的情况)。在内存中排列一致,导致intStruct和int可以相互转换。

当你在看apple开发文档时发现toll-free bridged这种字眼时(经常发生在NS***和CF***之间),表明它们是可以相互转换的,因为它们在内存中的排列是一致的。例如NSarray和CFArrayRef(NS为cocoa,CF为core foundation)

CFArrayRef arrayRef = //some value;

NSArray *array = (NSArray*)arratRef;

 

2、NSObject的定义

@interface NSObject<NSObject>{

 Class isa;

}

在编译过程中,@interface关键字告诉编译器:请将NSObject作为objective-c的一个类名,并将它转换成一个struct:

struct NSObject{

Class isa;

};

再考虑到所有的类都是NSObject的子类,所以推测:所有的object都是c的结构体。

 

3、再来看下Class的定义:

typedef struct obj_class *Class;

struct obj_class{

 Class isa

 Class super_class

 c*****t char *name

 long version

 long info

 long instance_size

 struct objc_ivar_list *ivars

 struct objc_method_list **methodLists

 struct objc_cache *cache

 struct objc_protocol_list *protocols

}

objc_class包含了objc类所需的所有信息,例如变量列表,方法列表,满足的protocol等等。这些信息可以通过gdb将感兴趣的信息打印出来.

我们注意到,NSobject和objc_class都有一个isa变量,NSObject的isa描述它的元信息(即object的类信息),objc_class描述类的类信息(即类的元信息)。这样,同object一样,class也是一种object,它在obj_class的isa中可以记录class method(用 + 声明的方法)。

Objc中的runtime reflection就是根据这信息操作的。

 

4、object定义的方法的转换

@implementation MyClass

 - (void)someMethod:(NSString*)param

@end

编译器会相应的转换为:

void [-someMethod:](id self, SEL _cmd, NSString *param){}

_cmd为方法的调用方(receiver), _cmd为方法签名(跟你用@selector得到的一样),后续为方法需要的参数。

当你调用方法时,objective-c会将方法调用都会转成c的方法调用。例如当你在程序里写如下语句时:

[myClass someMethod:@"bytedance"]

会相应的转换为:

objc_msgSend(myClass, @selector(someMethod:), @"bytedance")

@selector本质是一个c string,唯一与c string不同的是在整个内存空间中,同一方法签名的@selector的内存地址是相同的,这样在比较方法签名时候不需要采用同strcmp这么耗时的操作,而通过比较@selector的内存地址即可。

如果调用方没有找到相应的方法,会调用 [NSObject  resolveInstanceMethod]方法给调用方一次处理的机会

抱歉!评论已关闭.