跳转至

内存对⻬

struct的内存对⻬⽅式

1、数据成员对⻬规则

第⼀个数据成员放在offset为0的地⽅。

以后每个数据成员存储的起始位置要从该成员⼤⼩或者成员的⼦成员⼤⼩的整数倍开始(⽐如int为4字节,则要从4的整数倍地址开始存储)。

2、结构体作为成员

如果⼀个结构⾥有某些结构体成员,则结构体成员要从其内部最⼤成员的整数倍地址开始存储.(struct a⾥存有struct b,b⾥有char,int ,double等元素,那b应该从8的整数倍开始存储)。

3、收尾⼯作

结构体的总⼤⼩,也就是sizeof的结果必须是其内部最⼤成员的整数倍,不⾜的要补⻬。

数据类型占用内存的大小

1字节8位

数据类型 内存大小
char 1字节
bool 1字节
short 2字节
int 4字节
double 8字节
对象指针(NSString *) 8字节
isa指针 8字节
struct LGStruct1 {
    double a;   //8字节 [0 7]
    char b;     //1字节 [8]
    int c;      //4字节 [9 10 11 12 13 14 15]         其中9 10 11没用
    short d;    //2字节 [16 17]
}struct1;//需要24字节,8的整数倍。

结构体中有结构体

struct LGStruct1 {
    double a;   //8字节 [24 31]
    char b;     //1字节 [32]
    int c;      //4字节 [36 39]
    short d;    //2字节 [40 41]
}struct1;//需要24字节

struct LGStruct3 {
    double a;               //8字节 [0 7]
    int b;                  //4字节 [8 9 10 11]
    char c;                 //1字节 [12]
    short d;                //2字节 [14 15]
    int e;                  //4字节 [16 17 18 19]
    struct LGStruct1 str;   //
}struct3;//需要48个字节存储

对象的内存对齐

栈内存 连续的

创建的对象最小内存大小是16字节。

一个对象8字节,isa也是8字节,NSObject是8个字节,指针8字节。

为什么8为倍数, 而不是16或32:没有任何成员变量只有一个isa,则是8。

person中不同类型的成员变量占内存大小是不一样的,不断变化,CPU读取计算压力大。所以所有的成员变量都设置8字节。已8字节去读取,速度会变快(空间换时间)。

整个内存中8字节的最多,所以是8倍数。

8字节对齐

int func (int x) {
//    return (x + 7) / 8 * 8;
    return (x + 7) >> 3 << 3;//左移3 右移3
}

为什么要字节对⻬

字节是内存的容量单位。但是,计算机CPU在读/存内存的时候,不是以字节为单位来读取的,⽽是以“块”为单位读取的。所以会经常听到⼀块内存,“块”的⼤⼩也就是内存存取的⼒度。

如果不对⻬的话,在我们频繁的存取内存的时候,CPU就需要花费⼤量的精⼒去分辨你要读取多少字节,这就会造成CPU的效率低下,如果想要CPU能够⾼效读取数据,那就需要找⼀个规范,这个规范就是字节对⻬。

为什么对象内部的成员变量是以8字节对⻬,系统实际分配的内存以16字节对⻬?

堆内存中对象和对象之间是16字节对齐。

空间换时间。苹果采取16字节对⻬,是因为OC的对象中,第⼀位叫isa指针,它是必然存在的,⽽且它就占了8位字节,就算对象中没有其他的属性了,也⼀定有⼀个isa,那对象就⾄少要占⽤8位字节。如果以8位字节对⻬的话,如果连续的两块内存都是没有属性的对象,那么它们的内存空间就会完全的挨在⼀起,是容易混乱的。以16字节为⼀块,这就保证了CPU在读取的时候,按照块读取就可以,效率更⾼,同时还不容易混乱。