OC底层原理之《isa - 类的底层原理结构02》

一、内存偏移
图1

根据上图的打印结果我们可以看到a和b的地址指向的是同一片内存空间,这说明了内存空间可以被多个地址访问。而对象指针则是p本身指向了[JPerson alloc]开辟的空间。而&p则是指向了p。下图简单的表现了普通指针和对象指针的区别。


图2

重点,数组指针
图3
通过打印可知&c和&c[0]的地址是相同的说明了对于数组取地址,默认取的就是第一个元素的地址,而&c[1]的地址则是在首地址的基础上偏移了4个字节,因为int类型占用的字节数为4,所以通过偏移4个字节就能找到&c[1]。而d则为int类型指针,打印d的地址可以发现d的地址等于&c[0]的地址,说明了int *d = c就是指针d指向了数组c的第一个元素。通过打印 *(d+i)取值操作,说明了这一切。

二、方法的本质

在上一篇中我们已经分析了类的isa链和继承链,在此篇中我们将会着重介绍类,分析类中的方法,属性,成员变量等所在的位置。
通过OC对象本质这边文章可以得知isa实际上是继承于objc_object结构体的objc_class类型的结构体指针。

图4
那么我们定义的属性和方法在哪里呢,通过读代码可知在class_rw_t 里面,也就是bits.data。实际上就是在bits里面。
图5
通过内存偏移可知,[JPerson class] 获取的地址也就是JPerson内存结构的首地址,通过偏移一定的位置我们将会得到JPerson 里面的内容。那么如果要找到bits,需要偏移isa+superclass+cache。isa和superclass都是指针类型占8个字节,cache是cache_t类型,那么cache_t占用多少个字节呢,分析cache_t结构体可知,cache_t占用了16个字节。
图6.png
那么isa+superclass+cache = 32个字节。通过JPerson首地址偏移32个字节也就得到了bits的地址。
图8
已知JPerson中有以上元素,接下我们将获取JPerson中的各种元素。首先获取属性
图9
通过读内存的方式拿到了实例变量name和bobby,但是成员变量subject却不在properties列表里面。这里我们通过clang命令还原.cpp文件可以看到
图10
成员变量subject 在结构体_class_ro_t中,通过读源码可知成员变量的位置
图11
获取属性根据class_rw_t 结构体中的 method_array_t 方法列表可以获得对象方法
图12
通过输出所有的方法发现并没有类方法。尝试查找一下元类。
图13
在元类中发现类方法

总结

class的成员变量和实例变量在对应的class的property_array_t列表中,成员变量在ivars 中,class中存储对象方法,类方法存放在对应class的元类中。

和谐学习,不急不躁。

不积跬步无以至千里。

春风十里不如你,我在风里雨里雪里等你。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容