c++内存对齐

为什么需要内存对齐?

cpu在存取指令时,以字长为单位进行存取,32位机器的默认字长为4字节,64位机器的默认字长为8字节。cpu每次读u取时,都从对齐字长的整数倍开始读取,而存放数据时,cpu以对齐字长的整数倍进行存放,这要求我们对struct或class内的数据排布提出了要求。
假如没有内存对齐,数据被任意存放,cpu读取数据时,cpu需要先取出若干个对齐字长的内存,然后去掉开头和尾部不属于所需数据的字节,最后留下的数据块合并后再存入寄存器。考虑内存对齐的作用,cpu存取数据时可以直接取出若干对齐字节大小的数据,然后这直接存入寄存器,这显然比没有内存对齐要高效得多。

内存对齐规则

内存对齐时,struct第一个数据成员放置在offset为0的位置,后续数据成员的位置需要先确定对齐单位大小,每个数据成员的offset都是对齐单位的整数倍。

普通数据成员对齐

比如下面的代码中,对齐单位为8,char p1[11]大小本来应该为11个字节,但为了补齐后续缺失的字节,p1占据的大小会扩大为8x2=16字节,p2占据8字节,因此a的大小为24字节。

struct a{
    char p1[11];     //0~15
    long long p2;    //16~23
};

那么如何确定对齐单位大小呢?前面说过,以64位机器为例,默认字长为8字节,也通过下面的方式可以显式指定默认字长为n。

#pragma pack(n)

对每个数据成员,对齐单位的大小为默认字长和数据成员本身长度中较小的那个,比如下面的结构体。

struct b{
    char p1;          //1<8,对齐单位为1,0
    char p2;        //1<8,对齐单位为1,1
    short p3;         //2<8,对齐单位为2,2~3
    int p4;          //4<8,对齐单位为4,4~7
};//结构体大小为8

我们将上面的结构体稍微改变,就会看到变化。

struct c{   
    char p1;          //1<8,对齐单位为1,0
    short p2;         //2<8,对齐单位为2,2~3
    int p3;        //4<8,对齐单位为4,4~7
    int p4;         //4<8,对齐单位为4,8~12
};

struct结构体对齐

在每个数据成员都对齐后,struct本身也要对齐,struct会取出数据成员中最长的那个,与默认字长比较,取较小的那个作为对齐单位。

#pragma pack(4)
struct d{
    int p1;          //4=4,对齐单位为4,0~3
    char p2;         //1<4,对齐单位为1,4
    short p3;        //2<4,对齐单位为2,offset从6开始,6~7
    char p4;         //1<4,对齐单位为1,7
};//4=4,对齐单位为4,0~11

上面的结构体中,数据成员占据9个字节,但由于结构体对齐单位为4,因此扩充到了12个字节。
结构体中包含结构体时的对齐,与普通数据成员对齐规则相同,但结构体的长度按其最长的数据成员计算。

struct e{
    struct d p2;     //最大数据成员长度为4,4=4,以4为对齐单位
    char p1[5];      
};//5>4,对齐单位为5,结构体大小为20

union对齐

unoin是c++中一种特殊的结构体,这种结构体中的所有数据成员的起始地址相同,其内存大小按最长的数据成员计算:

union f{
    char p1;      
    char p2;       
    short p3;         
    int p4; 
};//内存按int大小算,为4

union同样也需要考虑内存对齐,规则与struct大致相同:

union g{
    int p1;
    short p2;         
    char p3[7]; 
};//7>4,对齐单位为4,结构体大小为8

对于多种结构体嵌套在一起的情况,也只需要通过上面介绍的规则分析,这里不再讨论。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值