深入浅出之C++内存对齐

先来一道大厂面试题:

struct Data1
{
	char a;
	uint32_t b;
	short c;
	char d;
}test1[3];

sizeof(test1)=?
这道题就是在考查内存对齐。至于答案是什么?别急,看完你就知道了。

什么是内存对齐

内存对齐本质就是数据存储的一个规则,即,数据按照对齐规则在内存中储存。
那么为什么会需要内存对齐呢?对齐的规则又是什么?

为什么需要内存对齐

以上面的面试题为例,假设没有内存对齐,那么结构体中的成员变量的内存就是连续分布的,如下图。
但在访问结构体变量时,是按结构体中成员所占的最大字节数对结构体进行读取的,而且每次只能从储存边界开始读取。在这个例子中,会按照uint32的大小,一次读取4个字节,每次只能从0、4开始读取。(注意:0-7代表相对于首地址的offset,并非实际地址。)
如果我们要获取b的内容,就需要两次读周期才可以将变量b从内存中读取出来,而且,还需要剔除和拼接操作。这就大大增加了读取的时间。
在这里插入图片描述
如果我们进行内存对齐呢?如下图所示,(pad代表我们为了进行内存对齐而填充的内存。)我们在读取b时,只用一个读周期就可以了,而且不需要剔除、不需要拼接。这与不对齐相比,是不是效率更高了呢。
在这里插入图片描述
看了上面的例子,现在清楚为啥要内存对齐了吧。主要就是为了性能,内存对齐可以提高数据访问效率。而且有的硬件架构,就要求你必须内存对齐,否则编译不通过。

对齐规则

一般平台上的编译器都有自己默认的“对齐系数”,可以通过预编译指令#pragma pack(n),n=1,2,4,8,16来改变对齐系数。(vs\vc中默认是n=8,gcc默认是n=4)

  • 基本原则:对于标准数据类型,它的地址只要是它的长度的整数倍就可以了。
  • 结构体对齐:
    • 结构体第一个成员的偏移量为0(也就是第一个成员变量的地址就是结构体的地址)
    • 以后每个成员相对于结构体首地址的offset=i*min(对齐系数,该成员长度),i为大于等于1的整数。就以上面的例子说明,变量a的offset为0,变量b的offset为多少呢?假设设置的对齐系数是8,变量b的长度是4,b的offset就是1*min(8,4)=4。(编译器会插入填充字节,确保满足对齐要求)
    • 结构体总体大小为有效对齐值的整数倍。(有效对齐值=min(对齐系数,最长变量的长度)。)上例中,长度最长的变量是b,长度为4,则有效对齐值=4。

答案

看完以上这些,你们知道开头那道题的答案了吗?
sizeof(test1)=36

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值