c++ 结构体对齐

C++结构体对齐

  • 内存对齐是一种提高内存访问速度的策略,CPU在访问未对齐的内存可能需要经过两次的内存访问,而经过内存对齐一次就可以了
cout<<"char:"<<sizeof(char)<<endl;
cout<<"int:"<<sizeof(int)<<endl;
cout<<"short:"<<sizeof(short)<<endl;
cout<<"float:"<<sizeof(float)<<endl;
cout<<"double:"<<sizeof(double)<<endl;

结构体对齐原则

  1. 数据成员对齐规则:结构的数据成员每个数据成员存储的起始位置要从该成员大小的整数倍开始,第一个是从0开始(因为0是任何整数的整数倍)
  2. 结构体作为成员:如果有一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍开始存储
  3. 结构体的总大小,必须是内部最大成员的整数倍
struct A1{
    char a1;
    int a2;
    char a3;
};

struct A2{
    char a1;
    char a2;
    int a3;
};

struct A3{
    char a1;
    int a2;
    double a3;
    char a4;
};

struct A4{
    char a1;
    struct A3 a2;
    int a3;
    double a4;
};
int main(){
    cout<<"A1:"<<sizeof(A1)<<endl;
    cout<<"A2:"<<sizeof(A2)<<endl;
    cout<<"A3:"<<sizeof(A3)<<endl;
    cout<<"A4:"<<sizeof(A4)<<endl;
}
  • 上面的输出结果为
A1:12
A2:8
A3:24
A4:48

A1

  • a1在offset为0的地方(长度为1,范围为0-0)
  • a2在offset为4的地方(长度为4,范围为4-7 )
  • a3在offset为8的地方(长度为1,范围为8-8)
  • 此时大小为9,但是使用规则3,结构体大小应该为其内部最大成员的整数倍,也就是4的整数倍,所以此时A1的大小为12,则此时a3后面三个字节被填充补齐,所以此时A1的范围是0-11

在这里插入图片描述

A2

  • a1在offset为0的地方(长度为1,范围是0-0)
  • a2在offset为1的地方(长度为1,范围是1-1)
  • a3在offset为4的地方(长度为4,范围是4-7)
  • 此时A2的大小为8

在这里插入图片描述

A3

  • a1在offset为0的地方(长度为1,范围是0-0)
  • a2在offset为4的地方(长度为4,范围是4-7)
  • a3在offset为8的地方(长度为8,范围是8-15)
  • a4在offset为16的地方(长度为1,范围是16-16)
  • 此时结构体大小为17,根据规则3,此时结构体大小应该为8的整数倍,也就是24,所以A3的大小为24

在这里插入图片描述

A4

  • a1在offset为0的地方(长度为1,范围是0-0)
  • 根据规则2,因为A3的成员最大为double8个字节,所以a2的offset为8(长度为24,范围是8-31)
  • a3在offset为32的地方(长度为4,范围是32-35)
  • a4在offset为40(长度为8,范围是40-47)
  • 所以结构体A4的大小为48

在这里插入图片描述

#pragma pack

  • #pragma pack(show) 会在编译阶段给出一个警告,说明当前对齐字节数,默认为8

  • #pragma pack() 将对齐字节数恢复成默认的对齐字节数

  • #pragma pack(n) n只能是1 2 4 8 16中的任意值,表示设置当前对齐字节数

  • #pragma pack(push) 将当前对齐字节数压入栈顶,并设这这个值为新的对齐字节数,也就是当前对齐字节数并没有改变

  • #pragma pack(push,n) 将当前对齐字节数压入栈顶,并设置n为新的对齐字节数

  • #pragma pack(pop) 会弹出栈顶对齐字节数,并设置为新的内存对齐字节数

  • #pragma pack(pop,n)弹出栈顶并直接丢弃,设置n为其新的内存对齐字节数

  • 在上面代码的最前面加上#pragma pack(1),则输出变为

A1:6
A2:6
A3:14
A4:27

这是因为将默认对齐字数改为1之后,在使用规则1 2 3进行计算的时候,都让1和之前大小取最小值,因为之前默认为8,所以可以获得之前的结果

A1

  • a1在offset为0的地方(长度为1,范围0-0)
  • a2在offset为1的地方(长度为4,范围为1-4),这是因为int的大小为4,之前默认对齐字节数为8,所以取4 8的最小值为4,将其放在4的整数倍上,而此时取值为4 1中的最小值为1,所以将其放在1的整数倍上
  • a3在offset为5的地方(长度为1,范围是5-5)
  • 之前默认对齐字数为8的时候,取得是数据成员变量最大值4和默认对齐字数8得最小值4,为结构体整体对齐得整数倍,而此时变为了4和1得最小值1,所以此时结构体应该是1的整数倍,所以结构体大小为6

其他三个结构体也是这么进行分析

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孙建钊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值