结构体字节对齐

结构体字节对齐

什么是对齐?为何要对齐?

  • 现代计算机中内存空间都是按照byte划分的,从理论上讲彷佛对任何类型的变量的访问能够从任何地址开始,但实际状况是在访问特定变量的时候常常在特定的内存地址访问,这就须要各种型数据按照必定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。
  • 若是不按照适合其平台要求对数据存放进行对齐,会在存取效率上带来损失。好比有些平台每次读都是从偶地址开始,若是一个int型(假设为32位系统)若是存放在偶地址开始的地方,那么一个读周期就能够读出,而若是存放在奇地址开始的地方,就可能会须要2个读周期,并对两次读出的结果的高低字节进行拼凑才能获得该int数据。显然在读取效率上降低不少。

#pragma pack()语法

  • #pragma pack 的主要做用就是改变编译器的内存对齐方式,这个指令在网络报文的处理中有着重要的做用,#pragma pack(n)是他最基本的用法,其做用是改变编译器的对齐方式, 不使用这条指令的状况下,编译器默认采起#pragma pack(8)也就是8字节的默认对齐方式,n值能够取(1, 2, 4, 8, 16) 中任意一值。
  • 咱们常说编译器默认8字节对齐咱们怎么知道的呢?#pragma pack(show)显示当前内存对齐的字节数。显示当前packing aligment的字节数,以warning message的形式显示。

image.png

结构体对齐的规则

原则1:数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,之后每一个数据成员的对齐按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。(即pack指定的值和成员自身比较,小的那个整数倍对齐)markdown

原则2:结构(或联合)的总体对齐规则:在数据成员完成各自对齐以后,结构(或联合)自己也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。(即pack指定的值和最大成员自身比较,小的那个整数倍对齐)网络

原则3:结构体做为成员:若是一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。数据结构

结构体对齐验证

#pragma pack(2)
struct Struct1{
    double a; //0-7
    char b;   //8
    int c;    //起始min(2,4)=2,因此从2的倍数开始 10 11 12 13
    short d;  //14 15
} structOne;  //min(2,8)=2, 2的倍数 16
#pragma pack()

struct Struct2{
    double a; //0-7
    char b;   //8
    int c;    //起始min(8,4)=4,因此从4的倍数开始 12 13 14 15
    short d;  //16 17
} structTwo;  //min(8,8)=8, 8的倍数 24 
复制代码

运行结果:大数据

image.png 能够看出此时structOne和structTwo,内部成员变量顺序彻底一致,指定了#pragma pack()以后sizeof获得的结果彻底不一样。spa

  • 那么若是编译器默认8字节对齐时,成员相同顺序不一样,结构体的字节又是多少呢?
#pragma pack(show)
struct Struct1{
    double a; //0-7
    char b;   //8
    int c;    //起始min(8,4)=4,因此从4的倍数开始 12 13 14 15
    short d;  //16 17
} structOne;  //min(8,8)=8, 8的倍数 24; 

struct Struct2{
    double a; //0-7
    int c;    //起始min(8,4)=4,因此从4的倍数开始 8 9 10 11
    char b;   //12
    short d;  //14 15
} structTwo;  //min(8,8)=8, 8的倍数 16
复制代码

运行结果code

image.png 能够看出结构体成员顺序不一样,虽然pragma pack相同,sizeof获得的字节数不一样。orm

  • 若是将structOne中的double a拆解成两个int成员,structOne的字节数应是20了

image.png

这是由于结构体总体对齐,是按照最大成员变量int长度的和pack默认的8中最小比较是4,4的最小倍数是20;内存

  • 结构体嵌套

image.png

image.png

  • 对比两张图明显发现,当出现结构体嵌套时,外层结构体总体对齐时,取得是内外结构体中最大成员变量的倍数

总结

结构体的对齐显示成员对齐,而后是结构体的总体对齐,根据内存对齐原则,来对齐内存。编译器

1:根据数据成员对齐:it

根据#pragma pack(x) 根据x这个数值和依次排列的数据成员自身的长度的数作比较,那个小用哪一个。

这样就排出来了每个数据所占的地址及位置。是依次排列,可是不是依次挨着排列,要排列的数据要看本身数据成员自身长度的数和x哪一个更小,假设自身数据长度为4,x为8,则再看本身要依次排列的地址是否是4的倍数,若是不是,则自动延长地址到4的倍数处,再赋值。

2:数据结构对齐:

当上面那个对齐了每个数据成员后, 如今须要对数据结构总体长度对齐。找出数据结构成员中最大长度的数据的值z,跟x作对比,找到最小的那个,假设x为8,z为4,则总体数据结构长度应该是4的整数倍,不够自动补齐。

3:结构体做为成员

若是成员内有结构体,须要看结构体中最大的成员的长度h来作比较,是h的倍数。

相关文章
相关标签/搜索