内存对齐是指,对于大小为x byte的变量,内存地址必须是x的整数倍。
- 数据成员对齐规则:结构体或者联合体的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始(比如int为4字节,则要从4的整数倍地址开始存储)。
- 结构体作为成员:如果一个结构体里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。
- 收尾工作:结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。
内存对齐是为了满足CPU访问内存中数据的效率问题,CPU访问内存需要遵循一定的规则。对于64位系统,CPU每次能从内存中拿出对齐的大小为8个字节的内存。
而内存对齐能够提高CPU访问数据的效率。ARM架构要求必须对齐,否则崩溃。
内存对齐可以减少访问次数从而提高效率。
OC | 32位 | 64位 |
---|---|---|
bool、BOOL | 1 | 1 |
char | 1 | 1 |
short | 2 | 2 |
int | 4 | 4 |
float | 4 | 4 |
long | 4 | 4 |
NSInteger | 4 | 8 |
CGFloat | 4 | 8 |
指针 | 4 | 8 |
double | 8 | 8 |
long long | 8 | 8 |
例子1:
struct LGStruct1 {
double a; // 8
char b; // 1
int c; // 4
short d; // 2
}struct1;
计算其内存大小,a:8字节, 从0开始存,【0-7】,b:1字节,【8】,c:4字节,根据规则要在整数倍的起始位置存,所以不能从9开始,只能往下找直到12,所以为【12-15】,d:2字节,【16-17】。全部大小为17,但是内部成员变量最大的内存为8,所以整个大小为8的倍数,24。
例子2:
struct LGStruct2 {
int a; //4
char b; //1
short c; //2
}struct2;
a:4个字节,从0开始存,【0-3】,c:1个字节,【4】,d:2个字节,【6-7】,整体大小为4 的倍数,所以是8。
例子3:
struct LGStruct3 {
char a; //1
int b; //4
short c; //2
struct LGStruct4 {
int a; // 4
double b; // 8
char c; // 1
short d; // 2
}struct4;
}struct3;
这个例子内部是嵌套结构体,结构体内部的结构体也需要根据其内部的最大成员变量的倍数作为起止位。
所以整体大小计算如:【0】,【4-7】,【8-9】,【16-19】,【24-31】,【32】,【34-35】。整体也要是其中最大的元素的倍数,所以大小是40。