首先我们来了解下
内存对齐的基本原则
- 数据成员对⻬规则:结构(struct)(或联合(union))的数据成员,第⼀个数据成员放在offset为0的地⽅,以后每个数据成员存储的起始位置要从该成员⼤⼩或者成员的⼦成员⼤⼩(只要该成员有⼦成员,⽐如说是数组,结构体等)的整数倍开始(⽐如int为4字节,则要从4的整数倍地址开始存储。min(当前开始的位置ab)a=10 b=4
10 11 12 13
- 结构体作为成员:如果⼀个结构⾥有某些结构体成员,则结构体成员要从其内部最⼤元素⼤⼩的整数倍地址开始存储.(structa⾥存有structb,b ⾥有char,int,double等元素,那b应该从8的整数倍开始存储.)
- 收尾⼯作:结构体的总⼤⼩,也就是sizeof的结果,.必须是其内部最⼤成员的整数倍.不⾜的要补⻬。
案列分析
创建一个继承于NSObject的对象CFPerson,添加一些属性
@interface CFPerson : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *nickName;
@property (nonatomic, assign) int age;
@property (nonatomic, assign) long height;
@property (nonatomic) char cha1;
@property (nonatomic) char cha2;
@end
再定义两个结构体
struct CFPersonOne{
double a;
char b;
int c;
short d;
}cfpersonOne;
struct CFPersonTwo{
double a;
int b;
char c;
short d;
}cfpersonTwo;
CFPerson *person = [CFPerson alloc];
person.name = @"CF";
person.nickName = @"xxf";
NSLog(@"%@",person);
NSLog(@"%lu-%lu",sizeof(cfpersonOne),sizeof(cfpersonTwo));
打印结果:
cfpersonOne和cfpersonTwo所占用的字节分别为24和16
为什么是这样的结果?
可以参考以下数据类型占用内存表
我们知道结构体的大小等于结构体属性只和,因此找到最大的属性。
就构体CFPersonOne解析
成员a为double类型,则占用8个字节
成员b为char类型,占用1个字节
成员c为int类型占4个字节
成员d为short类型占2个字节
根据内存对齐原则分析CFPersonOne的大小
成员a则从0号位开始排,即【0~7】
成员b则可以存放在8号位
成员c,需要存放4个字节,到此当前初始位置位9号位, 但初始位置并不是当前字节大小的整数倍,因此当前位置9号直到11号位不满足条件都需要废弃掉,因此c的起始位置应从12,开始移位直到15号位。即【12、13、14、15】
成员d,存放2个字节,初始位置到这为16号位,是当前字节的整数倍,即可以移动排号位16、17,即【16、17】
我们知道整个结构体的大小需要是当前结构体属性最大值的整数倍, 显然17不满足,则需要向上进行兼容,即最终结构体大小为24。
为什么要内存对齐?
内存对齐就是为了方便读取,用空间换时间。