iOS底层探索2-内存对齐

253 阅读5分钟

iOS底层探索-内存对齐

不同数据类型所占内存大小

图片.png

内存对齐原则

  • 1:数据成员对⻬规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的 整数倍 开始(比如int为4字节,则要从4的整数倍地址开始存储。 min(当前开始的位置m n) m=9 n=4 9 10 11 12
  • 2:结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储.(struct a里存有struct b,b里有char,int ,double等元素,那b应该从8的整数倍开始存储.)
  • 3:收尾工作:结构体的总大小,也就是sizeof的结果,.必须是其内部最大成员的整数倍.不足的要补⻬。

举例:

struct LGStruct1 {
    double a;       // 8    [0 7]
    char b;         // 1    [8]
    int c;          // 4    (9 10 11 [12 13 14 15]
    short d;        // 2    [16 17] 24  17+7=24
}struct1;

struct LGStruct2 {
    double a;       // 8    [0 7]
    int b;          // 4    [8 9 10 11]
    char c;         // 1    [12]
    short d;        // 2    (13 [14 15] 16
}struct2;

struct LGStruct3 {
    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]  24
    struct LGStruct1 str; 
    // (20 21 22 23 [24...47] 48  前面24+LGStruct1(17) = 41-7=48 或者[24+24]  48
}struct3;


struct LGStruct4 {
    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]  24
    struct LGStruct2 str; 
    //  (20 21 22 23 [24...39] 40 前面24+LGStruct2(16) = 40
}struct4;

打印一下

NSLog(@"%lu-%lu",sizeof(struct1),sizeof(struct2));
NSLog(@"%lu",sizeof(struct3));
NSLog(@"%lu",sizeof(struct4));

24-16
48
40

注:sizeof实际上是获取了数据在内存中所占用的存储空间,以字节为单位来计数。

分析

struct1
按照对齐规则
第一个数据成员 a 放在0的位置
double a8字节,a占位置为[0 7]
char b1字节,b占位置8(a后面每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的 `整数倍` 开始)81的整数倍  所以b8的位置开始占1位
int c 占4字节 同上 9不是4的整数倍  10 11 也不是 124的整数倍,所以c在12位置占4[12 13 14 15]
short d 占2字节 同上 162的整数倍,所以d在16位置占2[16 17]
没有结构体作为成员
收尾工作 结构体的总大小(sizeof)(必须是其内部最大成员的整数倍.不足的要补⻬), 17不是最大成员8字节的整数倍,要补齐,所以 结构体总大小24

struct2
double a8字节,a占位置为 [0 7]
int b4字节,占位位置 [8 9 10 11]84的倍数,在8的位置开始)
char c 占1字节,占位位置[12]
short d 占2字节,占位(13 [14 15] 
没有结构体作为成员
收尾工作 结构体的总大小(sizeof)(必须是其内部最大成员的整数倍.不足的要补⻬), 15不是最大成员8字节的整数倍,要补齐,所以 结构体总大小16

struct3
double a8字节,a占位置为 [0 7]
int b4字节,占位位置 [8 9 10 11]84的倍数,在8的位置开始)
char c 占1字节,占位位置[12]
short d 占2字节,占位(13 [14 15] 
int e 占4字节,占位[16 17 18 19]
struct LGStruct1 str 占24字节 从其内部最大元素大小8的整数倍开始即24开始 (20 21 22 23 [24...47]
有结构体作为成员 结构体成员要从其内部最大元素大小的整数倍地址开始存储.(struct 3里存有struct 1,1里有double,char,int,short等元素,那b应该从8(double)的整数倍开始存储.)
收尾工作 结构体的总大小(sizeof)(必须是其内部最大成员的整数倍.不足的要补⻬), 47不是最大成员8字节的整数倍,要补齐,所以 结构体总大小48

struct4
double a8字节,a占位置为 [0 7]
int b4字节,占位位置 [8 9 10 11]84的倍数,在8的位置开始)
char c 占1字节,占位位置[12]
short d 占2字节,占位(13 [14 15] 
int e 占4字节,占位[16 17 18 19]
struct LGStruct2 str 占16字节 从其内部最大元素大小8的整数倍开始即24开始 (20 21 22 23 [24...39]
有结构体作为成员 结构体成员要从其内部最大元素大小的整数倍地址开始存储.(struct 4里存有struct 2,2里有double,char,int,short等元素,那b应该从8(double)的整数倍开始存储.)
收尾工作 结构体的总大小(sizeof)(必须是其内部最大成员的整数倍.不足的要补⻬), 39不是最大成员8字节的整数倍,要补齐,所以 结构体总大小40

未完待续