美文网首页
002-OC对象原理探究 - 结构体内存对齐

002-OC对象原理探究 - 结构体内存对齐

作者: Mr_wick | 来源:发表于2021-06-16 15:40 被阅读0次

    引言

    上一篇文章,探究 alloc的过程中,提到内存对齐。下面我们通过对OC对象QLPerson探究来展开内存对齐的探究。

    OC对象本质

    我们探究oc对象底层的本质,通过如下方式,讲.m文件转为.cpp文件。参考我的这篇文章
    QLPerson.h 代码如下:

    image.png
    QLPerson.m 如下:
    image.png
    我通过xcrun来转成cpp文件
    xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc QLPerson.m -o QLPerson.cpp
    

    QLPerson.cpp拖入xcode,compile sources去掉QLPerson.cpp,使其不参与编译。在QLPerson.cpp中搜索QLPerson_找到底层实现为结构体QLPerson_IMPL

    image.png
    其中结构体NSObject_IMPL
    struct NSObject_IMPL {
        Class isa;
    };
    

    由此可得出OC对象的本质是结构体,引出我今天将要探究的结构体内存对齐

    结构体内存对齐探究:普通成员变量

    定义结构体代码如下:

    struct QLStruct1 {
        double  a;  // 8   
        char    b;  // 1   
        int     c;  // 4   
        short   d;  // 2   
    } struct1; 
    其中每个成员变量后面的注释为类型所占字节大小
    

    那么struct1的内存到底占多少呢?我们这里用sizeof()来计算结果:

    NSLog(@"%lu",sizeof(struct1));
    
    打印结果如下: image.png

    这24字节是怎么得到的?
    首先,我们要了解,结构体对齐有如下原则:

    1、数据成员对齐规则:结构(struct)或union的数据成员,第一个数据的成员,放在offset为0 的地方,以后每个数据成员存储的起始位置,要从该成员大小成员的子成员大小(只要该成员有子成员,数组、结构体等)的整数倍开始。
    2、结构体作为成员:如果一个结构里,有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。
    3、结构体的总大小,也就是sizeOf的结果,必须是其内部成员的整数倍,不足的要补齐
    
    根据内存对齐原则,得到下图是struct1的成员变量的分布情况(excel画的) image.png

    代码如下:

    struct QLStruct1 {
        double  a;  // 8   0 1 2 3 4 5 6 7
        char    b;  // 1   8
        int     c;  // 4   (9,10,11) 12 13 14 15
        short   d;  // 2   16 17
    } struct1;      // 总计:成员变量总和为17,收尾--最大成员变量double(8)的倍数 --> 24
    小括号为跳过
    

    9,10,11为什么会空出来,因为struct1的最大成员变量为double,也就是最大成员变量的大小为8字节,根据原则1,可知该结构体按8字节对齐。char b排到8后,int c本应该从9开始排,但是9不能被8整除,因此往后移到12开始分配4字节int c
    short d排布结束后,到了17,根据原则3struct1按照8字节内存对齐,不足的需要补齐,因此,最终sizeof(struct1)得到的是24而不是17

    结构体内存对齐探究:结构体作为成员变量

    struct QLStruct3 {
        double  a;              // 8    0-7
        int     b;              // 4    8 9 10 11
        char    c;              // 1    12
        short   d;              // 2    (13)14 15
        int     e;              // 4    16 17 18 19
        struct  QLStruct1 stru; // 17   (20,21,22,23)24 25 26 27 ... 40
    } struct3;                  // 总计:成员变量总和为40,收尾--最大成员变量double(8)的倍数 --> 48
    小括号为跳过
    

    根据探究普通成员变量的方式,根据原则2得到sizeof(struct3)的大小为48

    总结

    结构体内存对齐,要熟记以上3个原则,则面对复杂的结构体,也能得心应手的处理了。

    相关文章

      网友评论

          本文标题:002-OC对象原理探究 - 结构体内存对齐

          本文链接:https://www.haomeiwen.com/subject/mooxyltx.html