二、iOS內(nèi)存對齊

內(nèi)存對齊的規(guī)則

  • 1.數(shù)據(jù)成員對齊規(guī)則:結(jié)構(gòu)或聯(lián)合的數(shù)據(jù)成員,第一個(gè)數(shù)據(jù)成員放在offset為0的地方,以后每個(gè)數(shù)據(jù)成員存儲(chǔ)的起始位置要從該成員大小或者成員的子成員大小的整數(shù)倍開始
  • 2.如果一個(gè)結(jié)構(gòu)里有某些結(jié)構(gòu)體成員,則結(jié)構(gòu)體成員要從其內(nèi)部最大元素大小的整數(shù)倍地址開始存儲(chǔ)。(結(jié)構(gòu)體A里存有結(jié)構(gòu)體B,B里有char,int ,double等元素,那B應(yīng)該從8的整數(shù)倍開始存儲(chǔ))
  • 3.結(jié)構(gòu)體的總大小,也就是sizeof的結(jié)果,必須是其內(nèi)部最大成員的整數(shù)倍,不足的要補(bǔ)齊。

結(jié)構(gòu)體的內(nèi)存對齊

結(jié)構(gòu)體.png

iOS數(shù)據(jù)類型占用內(nèi)存大小,根據(jù)類型計(jì)算結(jié)構(gòu)體內(nèi)存大小

iOS數(shù)據(jù)類型占用內(nèi)存大小.png
結(jié)構(gòu)體 struct1 內(nèi)存計(jì)算
struct struct1{
    double a;   //8字節(jié) (0-7)
    char b;     //1字節(jié) (8)
    int c;      //4字節(jié) (12-15)
    short d;    //2字節(jié) (16-17)
}struct1;   //內(nèi)部需要大小:18。 最大屬性:8。 整個(gè)結(jié)構(gòu)體大?。航Y(jié)構(gòu)體整數(shù)倍 24。
struct1.png
  • \color{#F00000}{變量a} : 占8字節(jié),從0開始,0是8的倍數(shù),所以\color{#F00000}{0-7存儲(chǔ)a}
  • \color{#F00000}{變量b} : 占1字節(jié),從8開始,8是1的倍數(shù),所以\color{#F00000}{8存儲(chǔ)b}
  • \color{#F00000}{變量c} : 占4字節(jié),從9開始,9不是4的倍數(shù),繼續(xù)后移,12是4的倍數(shù),所以\color{#F00000}{12-15存儲(chǔ)c}
  • \color{#F00000}{變量d} : 占2字節(jié),從16開始,16是2的倍數(shù),所以\color{#F00000}{16-17存儲(chǔ)d}

因此\color{#F00000}{struct1}的需要的內(nèi)存大小為18字節(jié),而\color{#F00000}{struct1}中最大變量的字節(jié)數(shù)為8,所以 \color{#F00000}{struct1}實(shí)際的內(nèi)存大小必須是 8 的整數(shù)倍,18向上取整到24,24是8的整數(shù)倍,所以 \color{#F00000}{sizeof(struct1)} 的結(jié)果是 24

結(jié)構(gòu)體 struct2 內(nèi)存計(jì)算
struct struct2{
    double a;   //8字節(jié) (0-7)
    int b;      //4字節(jié) (8-11)
    char c;     //1字節(jié) (12)
    short d;    //2字節(jié) (14-15)
}struct2;   //整個(gè)結(jié)構(gòu)體大?。航Y(jié)構(gòu)體整數(shù)倍 16。
struct2.png
  • \color{#F00000}{變量a} : 占8字節(jié),從0開始,0是8的倍數(shù),所以\color{#F00000}{0-7存儲(chǔ)a}
  • \color{#F00000}{變量b} : 占4字節(jié),從8開始,8是4的倍數(shù),所以\color{#F00000}{8-11存儲(chǔ)b}
  • \color{#F00000}{變量c} : 占1字節(jié),從12開始,12是1的倍數(shù),所以\color{#F00000}{12存儲(chǔ)c}
  • \color{#F00000}{變量d} : 占2字節(jié),從13開始,13不是2的倍數(shù),繼續(xù)后移,14是2的倍數(shù),所以\color{#F00000}{14-15存儲(chǔ)d}

因此\color{#F00000}{struct2}的需要的內(nèi)存大小為15字節(jié),而\color{#F00000}{struct2}中最大變量的字節(jié)數(shù)為8,所以 \color{#F00000}{struct2}實(shí)際的內(nèi)存大小必須是 8 的整數(shù)倍,15向上取整到16,16是8的整數(shù)倍,所以 \color{#F00000}{sizeof(struct2)} 的結(jié)果是 16

結(jié)構(gòu)體 struct3 內(nèi)存計(jì)算(結(jié)構(gòu)體嵌套結(jié)構(gòu)體)
struct struct3{
    int b;      //4字節(jié) (0-4)
    char c;     //1字節(jié) (5)
    short d;    //2字節(jié) (6-7)
    int a;      //4字節(jié) (8-11)
    struct struct2 s; //16字節(jié)
}struct3;   //內(nèi)部需要大?。?7。 最大屬性:8(當(dāng)前結(jié)構(gòu)體及內(nèi)部結(jié)構(gòu)體最大屬性值)。 整個(gè)結(jié)構(gòu)體大?。航Y(jié)構(gòu)體整數(shù)倍 32。

\color{#F00000}{變量b}:占4個(gè)字節(jié),從0開始,0是4的倍數(shù),所以\color{#F00000}{0-4存儲(chǔ)b}
\color{#F00000}{變量c}:占1個(gè)字節(jié),從5開始,5是1的倍數(shù),所以\color{#F00000}{5存儲(chǔ)c}
\color{#F00000}{變量d}:占2個(gè)字節(jié),從6開始,6是2的倍數(shù),所以\color{#F00000}{6-7存儲(chǔ)d}
\color{#F00000}{變量a}:占4個(gè)字節(jié),從8開始,8是4的倍數(shù),所以\color{#F00000}{8-11存儲(chǔ)a}
\color{#F00000}{結(jié)構(gòu)體成員s}\color{#F00000}{s}是一個(gè)結(jié)構(gòu)體,根據(jù)\color{#F00000}{內(nèi)存對齊原則二},結(jié)構(gòu)體成員要從其內(nèi)部最大成員大小的整數(shù)倍開始存儲(chǔ),而\color{#F00000}{struct2}\color{#F00000}{最大的成員大小為8},所以s要從8的整數(shù)倍開始,12不是8的倍數(shù),需要往后移動(dòng)到16,16是8的整數(shù)倍,符合內(nèi)存對齊原則,所以\color{#F00000}{ 16-31 存儲(chǔ) s}.
因此\color{#F00000}{struct3}的需要的內(nèi)存大小為 \color{#F00000}{32字節(jié)},而\color{#F00000}{struct3}中最大變量為s, 其最大成員內(nèi)存字節(jié)數(shù)為8,根據(jù)內(nèi)存對齊原則,所以 \color{#F00000}{struct3} 實(shí)際的內(nèi)存大小\color{#F00000}{必須是 8 的整數(shù)倍},32正好是8的整數(shù)倍,所以 \color{#F00000}{sizeof(struct3 的結(jié)果是 32)}

內(nèi)存優(yōu)化(屬性重排)

定義一個(gè)LGPerson類

LGPerson.png

打印出LGPerson對象實(shí)際占的內(nèi)存大小及系統(tǒng)分配的內(nèi)存大小

LGPerson內(nèi)存大小.png

通過地址找到 name 和 nickName 屬性的值

內(nèi)存地址.png

age和height 直接存的值: age 是 int 類型 占4字節(jié),16進(jìn)制0x14 = 20。

數(shù)值型的存儲(chǔ).png

\color{#F00000}{蘋果針對age、c1、c2屬性的內(nèi)存進(jìn)行重排},age是int類型占4個(gè)字節(jié),c1和c2是char類型各占1個(gè)字節(jié),通過4+1+1的方式,按照\color{#F00000}{8字節(jié)對齊},不足補(bǔ)齊的方式\color{#F00000}{存儲(chǔ)在同一塊內(nèi)存}
age:0x00000014的值
c1: 存儲(chǔ)字符'a'的ACS碼值對應(yīng)的16進(jìn)制是 0x61
c2:存儲(chǔ)字符'b'的ACS碼值對應(yīng)的16進(jìn)制是 0x62

4.png
補(bǔ)充: 在LLDB中怎么查找double/float類型

double/float 進(jìn)行十六進(jìn)制轉(zhuǎn)換 ,需要特殊處理,有兩種方式:
首先添加屬性

//LGPerson 中  添加屬性
@property (nonatomic,assign) double weight;
------------------
// 在main 中添加 p.weight = 110.5;

第一種:反向查找
p/x (double)110.5


反向查找.png

第二種:正向查找,實(shí)現(xiàn)轉(zhuǎn)換方法

// float 轉(zhuǎn) 十六進(jìn)制并打印
void lg_float2HEX(float f){
    union uuf {float f; char s[4];} uf;
    uf.f = f;
    printf("0x");
    for (int i = 3; i >= 0; i--) {
        printf("%02x", 0xff & uf.s[i]);
    }
    printf("\n");
}
// double 轉(zhuǎn)十六進(jìn)制并打印
void lg_double2HEX(double d){
    union uud {double d; char s[8];} ud;
    ud.d = d;
    printf("0x");
    for (int i = 7; i >= 0; i--) {
        printf("%02x", 0xff & ud.s[i]);
    }
    printf("\n");
}
正向查找.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容