OC内存对齐基础

388 阅读5分钟

对齐原因

  • 平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。如基于 Alpha,IA-64,MIPS,和 SuperH 体系的... 拒绝读取未对齐数据。当一个程序要求这些 CPU 读取未对齐数据时,这时 CPU 会进入异常处理状态并且通知程序不能继续执行。所以,如果编译器不进行内存对齐,那在很多平台的上的开发将难以进行。
  • 性能原因:经过内存对齐后,CPU的内存访问速度大大提升。CPU 并不是以字节为单位存取数据的,它把内存当成是一块一块的,块的大小可以是2,4,8,16字节大小,因此CPU在读取内存时是一块一块进行读取的,每次内存存取都会产生一个固定的开销,减少内存存取次数将提升程序的性能,块大小成为memory access granularity(粒度)“内存读取粒度”。

内存对齐规则

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

举例

**

struct DRStruct1 {
    double a;
    char   b;
    int c;
    char d;
}MyStruct;
sizeof(MyStruct) = 24

struct DRStruct2 {
    char d;
    char   b;
    int c;
    double a;
}MyStruct1;
sizeof(MyStruct1) = 16

如上所示:结构体中只是将两个元素互换位置,结果所对应的size就不同,故此得出相同的变量,不同声明顺序就会导致结构体大小的不同。

解析

image.png MyStruct.png

  • MyStruct

    • a占用8个字节,起始位置为0,故此a所占位置为(0-7)

    • b占用1个字节,起始位置为8,根据内存对齐规则第一条,起始位置为所占空间的整数倍,可以直接后延,故此b所占位置为(8)

    • c占用4个字节,起始位置为9,而9并非4的整数倍,所以需要后移查找4的整数倍位置,最小为12,因此从12开始后延,位置为(12-15)

    • d占用1个字节,起始位置为16,符合对齐规则,直接后延,占用位置为16

    • 综上可得出MyStruct的中占用大小为17根据对齐规则第三条,占用大小应为最大长度成员变量的整数倍,上面成员最大为8,因此应为8的整数倍,最小为24,故此MyStruct的sizeof为24

image.png MyStruct1.png

  • MyStruct1

    • d占用1个字节,起始位置为0,故此d所占位置为(0)
    • b占用1个字节,起始位置为1,符合内存对齐规则,可以直接后延,故此b所占位置为(1)
    • c占用4个字节,起始位置为2,而2并非4的整数倍,所以需要后移查找4的整数倍位置,最小为4,因此从4开始后延,位置为(4-7)
    • a占用8个字节,起始位置为8,符合对齐规则,直接后延,占用位置为(8 - 15)
    • 综上可得出MyStruct的中占用大小为16,符合对齐规则第三条,故此MyStruct的sizeof为16

结构体嵌套结构体

**

typedef struct DRStruct1 {
    char   b;
    double c;
    char d;
}MyStruct;
sizeof(MyStruct) = 24

struct DRStruct2 {
    char d;
    char   b;
    MyStruct c;
}MyStruct1;
sizeof(MyStruct1) = 32

如上所示,结构体嵌套结构体时,并不是直接返回结构体大小的整数,而是查找结构体中子元素的最大长度的变量,上述代码中MyStruct中最大长度为c,对应的是8个字节,故此最终大小为8的整数倍。

解析

image.png

MyStruct1.png

  • MyStruct1

    • 由上面的解析可以得出MyStruct为24
    • DRStruct2中d占用1个字节,起始位置为0,占用位置为0
    • b占用1个字节,起始位置为1,占用位置为1
    • MyStruct占用24字节,起始位置为2,根据对其规则,其中最大的为double类型8个字节,故后延查找8的整数倍为8,由此得出从起始位置为8,占用位置为(8-31),共占用31个字节,为8的整数倍,符合对齐规则,得出MyStruct1的sizeof为32.

总结

排放过程中:

1.后面为数据成员,起点为该数据成员的占用字节大小的整数倍; 2.后面为结构体时,起点为结构体中最大元素大小的整数倍地址开始存储;

首尾对齐:

1.结构体中不管有/无嵌套结构体,补齐以所有元素中最大元素大小的整数倍对齐;

参考链接:www.jianshu.com/p/1d6d7b178…