前言
众所周知,OC是基于C和C++演变而来的,那么他的结构体对齐方式也是相似的,下面我们来进行分析下。
首先我们来说下内存对齐的原则,如下:
1. 数据成员对齐规则:结构体(struct)或联合(union)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如数组、结构体等)的整数倍开始(比如int为4字节,要从4的整数倍地址开始存储)
2. 结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。(struct a里存有struct b,b里有char,int,double等元素,那b应该从8的整数倍开始存储)
3. 结构体的总大小:也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。
各个数据类型所占的内存大小,如下图:
![](https://img.haomeiwen.com/i25536745/2874c81b432bf0cc.png)
实例分析
···
structLGStruct1 {
double a; // 8
char b; // 1
int c; // 4
short d; // 2
}struct1;
structLGStruct2 {
double a; // 8
int b; // 4
char c; // 1
short d; // 2
}struct2;
···
上述结构体struct1和struct2,成员个数和数据类型是一模一样的,我们按照正常的思维去分析,他们的sizeof大小一定是一致的,那么实际结果呢,我们来打印一下。
NSLog(@"%lu-%lu",sizeof(struct1),sizeof(struct2));
结果如下:
![](https://img.haomeiwen.com/i25536745/113e1a098980ce9c.png)
从上图可知,struct1和struct2所占大小是不一样的,这又是为什么,我们接下来进行详细分析下。
sturct1的分析结果如下:
1 double a, 所占大小是8字节,根据”结构体成员要从其内部最大元素大小的整数倍地址开始存储“,所以struct1要从0-7存double类型,
2 char b ,所占大小是1字节,所以存在第8个位置
3 int c,所占大小是4字节,根据"每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如数组、结构体等)的整数倍开始"原则,所以9,10,11丢掉,存在12,13,14,15位置
4 short d 所占大小是2字节,所以存在16,17的位置
所以struct1所占大小17字节,**根据”结构体的总大小:也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。“ **原则,struct1的实际所占大小是24字节。
我们再来分析struct2:
1 double a, 根据”结构体成员要从其内部最大元素大小的整数倍地址开始存储“,所以struct1要从0-7存double类型,
2 int b ,所占大小是4字节,根据"每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如数组、结构体等)的整数倍开始"原则,存在8,9,10,11的位置
3 char c,所占大小是1字节,所以存在第12个位置
4 short d,所以大小是2字节,13不能整除2,所以存在14,15的位置
所以struct2所占大小是15字节,根据**”结构体的总大小:也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。“ **原则,struct2的实际所占大小是16字节。
网友评论