内存字节对齐现象
我们首先通过两个结构体来观察iOS的内存字节对齐的现象。
typedef struct StructOne {
char a; //1字节
double b; //8字节
int c; //4字节
short d; //2字节
} MyStructOne;
typedef struct StructTwo {
double b; //8字节
int c; //4字节
short d; //2字节
char a; //1字节
} MyStructTwo;
NSLog(@"MyStructOne:%lu", sizeof(MyStructOne));
NSLog(@"MyStructTwo:%lu", sizeof(MyStructTwo));
上述代码打印出来的结果为:
MyStructOne:24
MyStructTwo:16
为什么定义相同的结构体,交换了变量在结构体中的顺序,结构体的内存大小就改变了呢?这就是iOS中“内存字节对齐”的现象。
内存字节对齐规则
每个特定平台上的编译器都有自己的默认“对齐系数”。可以通过预编译命令#pragma pack(n),n=1,2,4,8,16
来指定对齐系数,其中的n就是“对齐系数”,也是需要对齐的字节数。
在了解为什么要进行内存字节对齐之前,我们先来看看内存字节对齐的规则:
①数据成员对齐规则:结构体每个数据成员相对结构体的首地址的偏移量都是“对齐系数”的整数倍,如不满足,对数据成员进行填充字节以满足。可以使用后面的数据成员进行字节填充。
②结构体对齐规则:结构体的首地址是“对齐系数”的整数倍,结构体的总大小也是“对齐系数”的整数倍,如不满足,最后填充字节以满足。
验证字节对齐规则:
Xcode中默认为#pragma pack(8)
,也就是8字节对齐。如果在设置为#pragma pack(1)
就代表不进行内存对齐,之前两个结构体的内存大小就都是16了。
MyStructOne的进行内存字节对齐后的结构体为:
// Shows the actual memory layout
struct StructOne {
char a; // 1 字节
char _pad0[7]; //占位char[]用于补齐7字节以满足8的整数倍(条件1)
double b; // 8 字节,因为double能占满8字节,所以无法使用double追加在char后面来补齐
int c; // 4 字节
short d;