C语言中内存对齐原则:
1.首个成员的首地址为0;
2.每个成员的首地址是自身大小的整数倍;
补充说明:以4字节对齐为例,如果自身大小大于4字节,都以4字节整数倍为基准对齐。
例如:以前的成员内存对齐到13字节,成员本身是4字节,将13补齐为4的倍数,即为16;从16的以后的4个字节为该成员的存储地址;如果以前的成员内存对齐到12字节,成员本身是4字节,因12是4的倍数,不需要补齐;那么12以后的4个字节为该成员的存储地址。
3.最后以结构总体对齐;
补充说明:取结构体中最大成员类型所占内存倍数;以8字节对齐为例,如果超过8字节,都以8字节整数倍为基准对齐。(其中这一条还有个名字叫“补齐”,补齐的目的就是多个结构变量挨着摆放的时候也满足对齐的要求。)
例如:结构体中最大成员所占字节数为8,对齐后结构体所占的字节数为28,需要补齐为8的倍数,即为32;最后该结构体所占内存字节数为32;如果结构体中最大成员所占字节数为8,对齐后结构体所占的字节数为32,不需要补齐;最后该结构体所占内存字节数为32。
typedef struct {
char c; // 1 (1 + 7)
double d; // 8 8
int i; // 4 4
short s; // 2 2 最后22,取最大成员所占字节为8,最接近22的8的倍数为24,所以最后该结构体占24
} Struct1;
typedef struct {
double d; // 8 8
int i; // 4 4
char c; // 1 1 + 1
short s; // 2 2 最后16,取最大成员所占字节为8,16是8的倍数,所以最后该结构体占16
} Struct2;
// 输出:24-16
NSLog(@"%ld-%ld", sizeof(Struct1), sizeof(Struct2));
OC中内存对齐原则:
1.以C中对齐原则获取的OC对象所占内存;
2.OC对象的整体是以16的倍数进行对齐,及不满足16的倍数需要补足;
3.将1中获取的内存使其符合2中的条件,最终获取的内存,即为OC对象最中占用内存。
OC中如何获取对象的所占内存:
1.runtime中class_getInstanceSize方法:
获取的是类的实例变量的成员变量(ivar)所占用的大小(即实例对象实际使用的内存空间)。
2.malloc_size方法:
获得实例变量的指针指向的内存大小(即实例对象占用的内存空间),OC对象的整体是以16的倍数进行对其,及不满足16的倍数需要补足)。
@interface ZBYMAPerson : NSObject
@property (nonatomic, copy) NSString * name;
@property (nonatomic, assign) int age;
@property (nonatomic, assign) long height;
@property (nonatomic, copy) NSString * sex;
@end
@interface ZBYMATeacher : NSObject
@end
ZBYMAPerson * p = [ZBYMAPerson new];
// isa // 8
p.name = @"zby"; // 8
p.age = 32; // 4
p.height = 171; // 8
p.hobby = @"男"; // 8 36, 8的倍数为40,占用内存总数为40
ZBYMATeacher * t = [ZBYMATeacher new];
// isa // 8
// 输出:8-40-48 8-8-16
NSLog(@"%lu-%lu-%lu", sizeof(p), class_getInstanceSize(p.class), malloc_size((__bridge const void *)(p)));
NSLog(@"%lu-%lu-%lu", sizeof(t), class_getInstanceSize(t.class), malloc_size((__bridge const void *)(t)));
总结:这两个方法获取的内存不一定相等;因为class_getInstanceSize是以C语言中内存对齐原则获取的值,而malloc_size是OC中内存对齐原则获取的值。
网友评论