iOS - 内存对齐

2020-09-10  本文已影响0人  malgee

1、内存对齐是什么?

在计算机中,内存大小的基本单位是字节,理论上来讲,可以从任意地址访问某种基本数据类型。

但是实际上,计算机并非按照字节大小读写内存,而是一定倍数(8、16倍)的字节块来读写内存。因此,编译器会对基本数据类型的合法地址作出一些限制,即它的地址必须是一定倍数(8、16倍)。那么就要求各种数据类型按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。

2、内存对齐的原则

内存对齐应该是编译器的管辖范围,编译器为程序中的每个数据单元安排在适当的位置上,方便计算机快速高效的进行读取数据。

每个平台的编译器都有自己的对齐系数和相应的对齐规则。在iOS中的64位架构下,对齐系数就是8个字节。

2.1 数据成员对齐

结构体(struct)或联合体(union)中的成员变量中,首个成员变量放在偏移量为0的位置上,后面的成员变量的对齐偏移量是取指定对齐系数和本身该成员变量所占用大小中的较小值,即min(对齐系数,成员变量的内存大小 )

2.2 数据整体对齐

结构体(struct)或联合体(union)的数据成员中的成员变量完成自身的对齐之后,整个 结构体(struct)或联合体(union)也需要进行字节对齐处理,一般为min(对齐系数,最大成员变量的内存大小 )的整数倍。

结合上述原则1、2,可以推断出下面的常用原则,以结构体为例:

结合上述分析, 可以总结出内存对齐原则:

下表示各数据类型在iOS中占用的内存大小

image.jpeg

结构体内存对齐

接下来我们分析下结构体的内存分布

struct MGStruct1 {
    //           占字节数     起始位置            占的位置
    double a;   // 8         0                 (0 1 2 3 4 5 6 7)
    char b;     // 1         8                 (8)
    int c;      // 4         9         9 10 11 (12 13 14 15)
    short d;    // 2         16                (16 17)
}struct1;

// 结构体内部需要的内存大小为: 18
// 最大属性占用内存 : 8
// 结构体整数倍: 24
struct MGStruct2 {
    //           占字节数     起始位置            占的位置
    double a;   // 8         0                 (0 1 2 3 4 5 6 7)
    int c;      // 4         8                 (8 9 10 11)
    char b;     // 1         12                (12)
    short d;    // 2         13                (14 15)
}struct2;

// 结构体内部需要的内存大小为: 16
// 最大属性占用内存 : 8
// 结构体整数倍: 16
struct MGStruct3 {
    //           占字节数     起始位置            占的位置
    int c;      // 4         0                 (0 1 2 3)
    double a;   // 8         4         4 5 6 7 (8 9 10 11 12 13 14 15)
    char b;     // 1         16                (16)
    short d;    // 2         17             17 (18 19)
}struct3;

// 结构体内部需要的内存大小为: 20
// 最大属性占用内存 : 8
// 结构体整数倍: 24

控制台打印输出可以到处:

24      16      24
image.png

按照前面分析的内存对齐原则可以知道内存分布情况

image.png

注:空白部分为补齐的内存位置

struct1 为例做出分析内存大小过程如下:

按照内存对齐原则分析得出:struct1最大变量字节数为8,分析完成4个属性(a, b, c,d)需要18字节内存, 而实际的内存大小必须是 8 的整数倍,18向上取整到24,主要是因为24是8的整数倍,所以sizeof(struct1) 的结果是 24

结构体嵌套结构体

定义一个嵌套结构体 struct2_1_1

struct Struct2_1_1 {
    //           占字节数     起始位置            占的位置
    int c;      // 4         0                 (0 1 2 3)
    double a;   // 8         4                 (8 9 10 11 12 13 14 15)
    struct Struct3 struct3;   // 8             (16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39)  ==> struct3 内存大小 24
    char b;     // 1         40                (40)
    short d;    // 2         41                (42 43)
}struct2_1_1;  // => 48

分析过程:

因此struct2_1_1需要的内存大小44字节, 而 struct2_1_1中的最大属性占用8字节, 根据内存对齐原则可以 得出 结构体的内存大小必须是8的整数倍,即sizeof(struct2_1_1) = 48

内存分析图:

image.png

注:空白部分为补齐的内存位置

更多结构体分析可以查看demo
上一篇 下一篇

猜你喜欢

热点阅读