内存对齐时为什么结构体的最终大小需要是其最大成员大小的整数倍

来源:互联网 发布:信鸽分类信息软件 编辑:程序博客网 时间:2024/06/08 14:23

本文主要记录博主在研究内存对齐时遇到的一个疑问,及最终疑问的解答。

至于 什么是内存对齐、为什么要内存对齐、内存对齐的规则,网上一搜一大堆,这里就不记录了。


内存对齐时,结构体分配内存大小会满足两个条件:

1. 假设第一个成员的起始地址为0,每个成员的起始地址(startpos)必须是其数据类型所占空间大小的整数倍。

2. 结构体的最终大小必须是其成员(基础数据类型成员)里最大成员所占大小的整数倍。


其中,第一条起始地址特殊要求的原因(实际上就是内存对齐的原因)网上依然一搜一大把,主要是提高处理器访问内存的速度。

但第二条又是为什么呢?为什么要在所有成员都对齐以后又对整体大小做了要求?

查了一圈没有查到,最后在stackoverflow似乎找到了答案。

贴上原文地址:http://stackoverflow.com/questions/10309089/why-does-size-of-the-struct-need-to-be-a-multiple-of-the-largest-alignment-of-an


以下是看完帖子后的个人理解,若是不对还请各位指出。

个人理解:第二条实际上还是为了内存对齐,如果没有第二条来善后,那第一条的工作就有可能白做了。举个例子

struct st{    int32_t a;    int8_t  b;};struct st arr[N];

结构体 st 如果在最后没有进行填充则应该是5个字节,若做了填充则是8个字节。而底下数组arr的地址分配则会受到结构体 st 大小的影响。

假设数组的起始地址为0,那么

st 为5字节时,arr[0] 占用 0-4,arr[0].a的startpos为0,arr[0].b的startpos为4;arr[1] 占用 5-9,arr[1].a的startpos为5,arr[1].b的startpos为9。可以看到arr[1]的内部成员a并没有对齐(startpos不是其数据类型大小的整数倍),借用帖子里的话 arr[1].a 会cross lines。

st 为8字节时,arr[0] 占用 0-7,arr[0].a的startpos为0,arr[0].b的startpos为4;arr[1] 占用 8-15,arr[1].a的startpos为8,arr[1].b的startpos为12。依次类推数组里所有结构体成员及所有结构体的内部成员都会对齐。

因为基础数据类型的数据大小无非就是1 2 4 8 16字节,若结构体的总大小是最大基础成员大小的整数倍,那么也就一定是其他任一基础成员大小的整数倍,那么每个结构体的startpos就一定是其任一基础成员大小的整数倍 ,这样的话,两条规则结合在一起就保证了所有基础类型数据、非基础类型数据全部对齐。


0 0
原创粉丝点击