这篇文章我们来讲讲关于内存对齐的一些趣事
为什么要内存对齐
- 平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
- 性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。
内存对齐的规则
- 数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员的大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始(比如int为4字节,则要从4的整数倍地址开始存储)。min(当前开始的位置m n) m = 9 n = 4 9 10 11 12
- 结构体作为成员:如果一个结构体有其他结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。(struct a里存有struct b,b里有char,int,double等元素,那么b应该从8的整数倍开始存储)
- 收尾工作:结构体的总大小,也就是sizeof的结果,必须是内部成员最大成员的整数倍,不足的要补齐。
各类型所占内存大小
我们通过例子来了解结构体的内存对齐算法
那么我们来讲解struct1结构体的内存计算
- a:double类型,占用8个字节,从【0-7】计算
- b:char类型,占用1个字节,从8个字节计算并且8是1的整数倍,所以占用字节(8)
- c:int类型,占用4字节,但是因为9,10,11都不是4的整数倍,12是4的整数倍,所以从12字节开始计算,占用的内存是(12,13,14,15)
- d:是short类型类型,占用2个字节,从16开始计算,暂用内存(16,17)
- 内存需要的大小:0~17 = 18
- 最大属性: 8
因为当前的内存大小是18,同时又要是8的整数倍,因此结构体的整数倍就是24。
结构体struct1是一样的原理。
结构体嵌套结构体
上面的两个结构体只是简单的定义数据成员,下面来一个比较复杂的,结构体中嵌套结构体的内存大小计算情况
- a:double类型,占用8个字节,从【0-7】计算
- b:char类型,占用1个字节,从8个字节计算并且8是1的整数倍,所以占用字节(8)
- c:int类型,占用4字节,但是因为9,10,11都不是4的整数倍,12是4的整数倍,所以从12字节开始计算,占用的内存是(12,13,14,15)
- d:是short类型类型,占用2个字节,从16开始计算,暂用内存(16,17)
- 内存需要的大小:16+24 = 40
- 最大属性: 8
因此LGStruct2的需要的内存大小为 16字节,而LGStruct1中最大变量为str, 其最大成员内存字节数为8,根据内存对齐原则,所以 LGStruct1 实际的内存大小必须是 8 的整数倍,24正好是8的整数倍,所以 LGStruct2的内存大小的结果是 40。
网友评论