美文网首页
结构体内存字节对齐规律

结构体内存字节对齐规律

作者: CrazySnow | 来源:发表于2020-09-08 14:33 被阅读0次

    结构体是由一批数据组合而成的一种新的数据类型。组成结构型数据的每个数据称为结构型数据的“成员”。
    结构体指针的大小是8字节,结构体的大小是根据结构体成员的大小累积计算。

    字节对齐的好处

    内存存取粒度:处理器并不是按字节块来存取内存的.它一般会以双字节,四字节,8字节,16字节甚至32字节为单位来存取内存.我们将上述这些存取单位称为内存存取粒度。

    • CPU的数据总线宽度决定了CPU对数据的吞吐量
    • 64位CPU一次处理64 bit也就是8个字节的数据,32同样,每次处理4个字节的数据

    字节对齐规则

    基本数据类型的大小.png
    • 数据成员对齐规则:struct 或者union的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如数据、结构体等)的整数倍开始
    • 数据成员为结构体:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储
      结构体的整体对齐规则:结构体的总大小,即sizeof的结果,必须是其内部做大成员的整数倍,不足的要补齐
      以下面结构体为例,计算Student结构体的大小:
    struct Student {
            bool sex;    
    //$\color{red}{1个字节}$  (0,1) 放在第0位,长度为1;起始位置是0
            short int age;
    //  $\color{red}{2个字节}$ (2,2)放在第2位长度为2;起始位置是2
     //$\color{red}{*为什么没有放在第一位,起始位置必须是长度的整数倍,1不是2的整数倍}$
            void *address; 
    // $\color{red}{8个字节}$(8,8)放在第8位,长度是8;起始位置是5,6,7,8;8是8的整数倍,所以起始位置是8
            float grade; 
    // $\color{red}{4个字节}$(16,4)放在第16位,长度是4;起始位置是16;
            char  name[9];
    // $\color{red}{9个字节}$(20,9)放在第29位,长度为9;起始位置是20;
    // $\color{red}{*char是一个字节,虽然char  name[9]占9个位置,但是起始位置必须是长度(数据类型的长度)的倍数}$
    };
    

    结构体的大小是结构体中最大元素的整数倍,Student结构体中,char的长度是8,故Student结构体的大小为32

    结构体内存计算图示.png
    针对结构体嵌套的情况
    struct Student2 {
      bool sex;
      short int age;
      void *address;
      float grade;
      char  name[9];
      Student1 stu;
    };
    

    结构体嵌套,最终的大小并不是Student2结构体内最大的元素的倍数,而是Student1Student2所有子元素里,最大的那一个的倍数,所以Student2的大小是8的倍数,按照上面的排列规则,得出结果是53,但是结果必须是8的倍数,故最终结果是56

    字节重排

    当我们在定义结构体时,如果数据成员的定义顺序安排的不合理就有可能会导致多余内存空间的占用和浪费。 为了达到最佳内存空间占用,系统在计算内存大小的时候,会对结构体内的元素进行重排,按照从小到大的原则重新排列,下图是Student1重排后的结果。

    内存优化.png

    相关文章

      网友评论

          本文标题:结构体内存字节对齐规律

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