内存对齐时为什么结构体的最终大小需要是其最大成员大小的整数倍
2017-05-13 22:33
375 查看
本文主要记录博主在研究内存对齐时遇到的一个疑问,及最终疑问的解答。
至于 什么是内存对齐、为什么要内存对齐、内存对齐的规则,网上一搜一大堆,这里就不记录了。
内存对齐时,结构体分配内存大小会满足两个条件:
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
以下是看完帖子后的个人理解,若是不对还请各位指出。
个人理解:第二条实际上还是为了内存对齐,如果没有第二条来善后,那第一条的工作就有可能白做了。举个例子
结构体 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就一定是其任一基础成员大小的整数倍 ,这样的话,两条规则结合在一起就保证了所有基础类型数据、非基础类型数据全部对齐。
至于 什么是内存对齐、为什么要内存对齐、内存对齐的规则,网上一搜一大堆,这里就不记录了。
内存对齐时,结构体分配内存大小会满足两个条件:
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 ;
结构体 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就一定是其任一基础成员大小的整数倍 ,这样的话,两条规则结合在一起就保证了所有基础类型数据、非基础类型数据全部对齐。
相关文章推荐
- 结构体内存对齐规则总结-整体单个排列/成员之间没有边界只有最后的填充/最后是最大类型整数倍
- C语言之struct大小、首地址与内存对齐—由结构体成员地址得到结构体首地址
- 结构体成员的内存分布与对齐
- 为什么内存不对齐需要两次访问内存?
- C++学习之旅——结构体和联合体的区别,以及数据对齐方式影响内存大小
- 结构体和联合体的大小,结构体内存对齐的原因、规则以及柔性数组
- C++中结构体的大小与内存对齐
- C++ 内存对齐 (计算结构体的大小)
- 内存对齐方式的总结 如何计算结构体所占内存的大小
- [转]关于结构体成员内存对齐的问题
- 如何求出C语言结构体中各个成员的大小及内存偏移量
- 结构体成员内存分布与对齐
- 结构体获取成员偏移值、结构体内存中字节对齐问题
- 结构体的内存对齐方式(结构体大小计算 sizeof)(
- 结构体成员的内存分布与对齐
- C++学习之旅——结构体和联合体的区别,以及数据对齐方式影响内存大小
- C/C++ 结构体成员在内存中的对齐规则(转载)
- C/C++中结构体与类成员变量在存储上的内存对齐问题
- 为什么需要内存对齐?
- C++ 获取结构体内存对齐后的每个字段的大小