示例代码:
struct StudentOne {
char a; //1字节
double b; //8字节
int c; //4字节
short d; //2字节
} MyStudent1;
struct StudentTwo {
double b; //8字节
char a; //1字节
short d; //2字节
int c; //4字节
} MyStudent2;
NSLog(@"%lu---%lu--", sizeof(MyStudent1), sizeof(MyStudent2));
打印结果:24---16--
此时,相同的结构体,只是交换了变量 ab 在结构体中的顺序他们的大小就改变了
总结:内存对齐的原则:
1:数据成员对⻬规则:结构(struct)(或联合(union))的数据成员,第
一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要
从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,
结构体等)的整数倍开始(比如int为4字节,则要从4的整数倍地址开始存
储。
2:结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从
其内部最大元素大小的整数倍地址开始存储.(struct a里存有struct b,b
里有char,int ,double等元素,那b应该从8的整数倍开始存储.)
3:收尾工作:结构体的总大小,也就是sizeof的结果,.必须是其内部最大
成员的整数倍.不足的要补⻬。
MyStudent1 的进行对齐后结构为:
struct StudentOne { char a; // 1 byte char _pad0[7]; //补齐7字节成为8(随后跟着的 double 大小)的倍数,原则一 double b; // 8 bytes int c; // 4 bytes short d; // 2 byte char _pad1[2]; // 补齐2字节让结构体的大小成为最大成员大小double(8字节)的倍数,原则二 } MyStudent1;
验证结果,打印结构体:
long a = (long)&MyStudent1.a; long b = (long)&MyStudent1.b ; long c = (long)&MyStudent1.c; long d = (long)&MyStudent1.d; NSLog(@"MyStudent1大小---%lu------", sizeof(MyStruct1)); NSLog(@“内存地址---%ld,%ld,%ld,%ld", a, b, c, d);
输出的结果为:MyStudent1大小—--24 ;内存地址---4539371424,4539371432,4539371440,4539371444。他们的内存占用符合内存对齐的规则。
char a + char _pad0[7] : 4539371424 // 占用 24-31
double b : 4539371432 // 占用 32-39
int c : 4539371440 // 占用 40-43
short d + char _pad1[2]: 4539371444 // 占用 44-47
通过上述规则进行对齐后的 MyStudent1 增加了 9 个字节变为 24 字节。而 MyStruct2 的所有数据成员和结构体本身只有 a 运用内存对齐的规则一增加了一个字节,所以大小为 16 字节。
为什么要进行内存对齐
内存对齐应该是编译器的管辖范围。编译器会为程序中的每个数据单元安排在适当的位置上,这个过程对于大部分程序员来说都应该是透明的。但如果你想了解更加底层的秘密,“内存对齐”就不应该对你透明了。
网友评论