本章主要由结构体内存对齐到苹果的属性重排, 以及
16字节对齐算法
0x00 -- 获取内存大小的三种方式
Person *person = [Person alloc];
person.name = @"xxxxx";
person.nickName = @"ddd";
NSLog(@"%@ - %lu - %lu - %lu",
person,
sizeof(person),
class_getInstanceSize([Person class]),
malloc_size((__bridge const void *)(person)));
// 输出 8 - 40 - 48
获取内存大小的三种方式:
sizeof(expression-or-type)
小提示 💡: sizeof的三种语法形式:
int a = 10;
size_t a1 = sizeof(a); // 4
size_t a2 = sizeof a; // 4
size_t a3 = sizeof(int); // 4
int *pa = &a;
size_t p1 = sizeof(pa); // 8
size_t p2 = sizeof pa; // 8
size_t p3 = sizeof(int *); // 8
NSObject *obj = [NSObject alloc] ;
size_t o1 = sizeof(obj); // 8
size_t o2 = sizeof obj; // 8
size_t o3 = sizeof(NSObject*);// 8
sizeof()是操作符,不是函数;其作用是返回一个对象或者类型所占的内存字节数。基本数据类型
int,char,double,float等这样简单内置数据类型,它们的大小和系统相关, 不同系统下取值也不一样。如果是结构体,
sizeof涉及到字节对齐的问题,根据计算机组成原理教导我们这样有助于加快计算机的取数速度,否则多话指令周期。让宽度为2的节本数据类型short等,都位于能被2整除的低智商;让宽度为4的基本数据类型int等,都位于能被4整除的地址上,以此类推,这样,俩个数中间就可能需要加入填充的字节,所以整个结构体的sizeof值就增长了。
class_getInstanceSize这个RuntimeAPI是获取cls这个类所创建实例对象实际占用的内存大小,也就是实例对象大小
size_t class_getInstanceSize(Class cls)
{
if (!cls) return 0;
return cls->alignedInstanceSize();
}
// Class's ivar size rounded up to a pointer-size boundary.
uint32_t alignedInstanceSize() const {
return word_align(unalignedInstanceSize());
}
#ifdef __LP64__
# define WORD_SHIFT 3UL
# define WORD_MASK 7UL
# define WORD_BITS 64
#else
# define WORD_SHIFT 2UL
# define WORD_MASK 3UL
# define WORD_BITS 32
#endif
static inline uint32_t word_align(uint32_t x) {
return (x + WORD_MASK) & ~WORD_MASK;
}
通过源码可知道 class_getInstanceSize函数获取的的对象大小是8字节对齐。
这个函数依据对象内部的属性变化而变化;如果没有属性, 只继承了NSObject,则类的实例对象实际占用的内存大小是8,
malloc_size
这个函数位于#import <malloc/malloc.h>头文件中,获取的是指针所指向内存大小
malloc_size是系统实际开辟的内存空间,class_getInstanceSize是实际占用的空间。根据文章顶部
代码实例1打印可验证。这个是由系统完成的,从上面的分析看得出, 实际占用和实际分配的大小是不一样的。 例如: 系统根据一定对齐算法为你这个对象开辟了32字节,但你这个Class类所创建的对象实际只占用16字节。就这么个意思。