OC 结构体内存对齐

553 阅读3分钟

首先我们先来看一下这张内存占用图

image.png

结构体定义

首先我们先来看看下面这段代码,struct1struct2 他们的内存占用总大小是否一样? 会不会因为它们的顺序不同占用的内存会不一样呢? 它们内存占用分别是多少呢? 我们继续往下看...

struct LGStruct1 {
    BOOL a;
    float b;
    double c;
    char d;
}struct1;

struct LGStruct2 {
    double a;
    char b;
    BOOL c;
    float d;
}struct2;

根据 内存占用图内存对齐原则 , 我们可以计算出 struct1struct2 各自分别占用的内存...(如果有同学对 内存对齐原则 不是很了解的可以再文末查看.)

struct LGStruct1 {
    BOOL a;     //  1 byte  [0]
    float b;    //  4 byte  (1,2,3,[4,5,6,7]
    double c;   //  8 byte  [8,9,10,11,12,13,14,15]
    char d;     //  1 byte  [16]
                // 共 17 个字节
                // 根据内存对齐原则: 结构体的总大小(sizeof的结果),必须是其内部最大成员的整数倍,不足的要补⻬。
                // 17 不是 8 的整数倍,将内存大小由 17 补齐到 8 的整数倍即为 24
                // sizeof = 24
            
}struct1;

struct LGStruct2 {
    double a;   //  8 byte  [0,1,2,3,4,5,6,7]
    char b;     //  1 byte  [8]
    BOOL c;     //  1 byte  [9]
    float d;    //  4 byte  (10,11,[12,13,14,15]
                // 共 16 个字节
                // 根据内存对齐原则: 结构体的总大小(sizeof的结果),必须是其内部最大成员的整数倍,不足的要补⻬。
                // 16 是 8 的整数倍
                // sizeof = 16
}struct2;

如下图我们可以看到我们计算的结果和打印的 sizeof(struct1)sizeof(struct2) 是一样的。

image.png

图示如下: image.png

以上我们了解了单个结构体内存对齐,接下来我们再看看嵌套结构体内存是怎么计算的呢?

struct LGStruct3 {
    BOOL a;     //  1 byte  [0]
    float b;    //  4 byte  (1, 2, 3, [4, 5, 6, 7]
    double c;   //  8 byte  [8, 9, 10, 11, 12, 13, 14, 15]
    char d;     //  1 byte  [16]
    // 结构体内部最大元素为double(8 byte),当前偏移量为17,不是8的整数倍,所以从24开始存放接下来的struct Inside
    struct Inside {
        int e;      // 2 byte   [24, 25]
        double f;   // 8 byte   (26, 27, 28, 29, 30, 31, [32, 33, 34, 35, 36, 37, 38, 39]
        char g;     // 1 byte   [40]
    }inside;
    // 共 41 个字节
    // 根据内存对齐原则: 结构体的总大小(sizeof的结果),必须是其内部最大成员的整数倍,不足的要补⻬。
    // 41 不是 8 的整数倍, 将内存大小由41 补齐到 8 的整数倍即为 48
    // sizeof = 48
}struct3;

我们来运行一下这段代码,看下我们计算的结果和系统计算的结果是否一致.

image.png

图示如下: image.png

内存对齐原则

  1. 数据成员对⻬规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始(比如int为4字节,则要从4的整数倍地址开始存储。

  2. 结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始储.(struct a里存有struct b,b里有char,int ,double等元素,那b应该从8的整数倍开始存储.)

  3. 结构体的总大小(sizeof的结果),必须是其内部最大成员的整数倍,不足的要补⻬。