本文主要记录博主在研究内存对齐时遇到的一个疑问,及最终疑问的解答。
至于 什么是内存对齐、为什么要内存对齐、内存对齐的规则,网上一搜一大堆,这里就不记录了。
内存对齐时,结构体分配内存大小会满足两个条件:
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就一定是其任一基础成员大小的整数倍 ,这样的话,两条规则结合在一起就保证了所有基础类型数据、非基础类型数据全部对齐。