內(nèi)存對(duì)齊

內(nèi)存對(duì)齊指的是結(jié)構(gòu)體中對(duì)結(jié)構(gòu)成員內(nèi)存的一系列調(diào)整师骗。通過(guò)調(diào)整offset位置通孽,減少讀取結(jié)構(gòu)成員數(shù)據(jù)需要的CPU-> 內(nèi)存讀取次數(shù)。任何對(duì)象數(shù)據(jù)在底層實(shí)際上是結(jié)構(gòu)體拙友。

對(duì)齊規(guī)則

1为狸、數(shù)據(jù)成員對(duì)齊規(guī)則:結(jié)構(gòu)(struct)(或聯(lián)合(union))的數(shù)據(jù)成員,第一個(gè)數(shù)據(jù)成員放在offset為0的地方遗契,以后每個(gè)數(shù)據(jù)成員的對(duì)齊按照#pragma pack指定的數(shù)值和這個(gè)數(shù)據(jù)成員自身長(zhǎng)度中钥平,比較小的那個(gè)進(jìn)行

2、結(jié)構(gòu)(或聯(lián)合)的整體對(duì)齊規(guī)則:在數(shù)據(jù)成員完成各自對(duì)齊之后涉瘾,結(jié)構(gòu)(或聯(lián)合)本身也要進(jìn)行對(duì)齊知态,對(duì)齊將按照#pragma pack指定的數(shù)值和結(jié)構(gòu)(或聯(lián)合)最大數(shù)據(jù)成員長(zhǎng)度中,比較小的那個(gè)進(jìn)行立叛。

3负敏、結(jié)合1、2可推斷:當(dāng)#pragma pack的n值等于或超過(guò)所有數(shù)據(jù)成員長(zhǎng)度的時(shí)候秘蛇,這個(gè)n值的大小將不產(chǎn)生任何效果其做。

是不是有一點(diǎn)眼暈?我自己總結(jié)的計(jì)算方法如下:

內(nèi)存對(duì)齊原則 (簡(jiǎn)化版):

  1. 找到最大的基礎(chǔ)類(lèi)型成員 , 將其內(nèi)存長(zhǎng)度作為基準(zhǔn)
  2. 每個(gè)成員的offset赁还,需要是成員自己類(lèi)型的整數(shù)倍
  3. 放完之后妖泄,struct自身的數(shù)據(jù)需要為基準(zhǔn)的整數(shù)倍

讓我們看一個(gè)簡(jiǎn)單的數(shù)據(jù):

struct Struct1 {
    double a; // 8
    char b;   // 1
    int c;    // 4
    short d;  // 2
}struct1;

1. 最長(zhǎng)的元素是double,基準(zhǔn)為8
2.
struct Struct1 {
    double a; // 長(zhǎng)度為8 offset:0艘策,0是8的整數(shù)倍蹈胡,所以 a存放位置為 (0 - 7)
    char b;   //  長(zhǎng)度為1 offset: 8  8是 1的整數(shù)倍,所以 b存放位置為 (8)
    int c;    //  長(zhǎng)度為4 offset: 9  9不是4的整數(shù)倍朋蔫,offset后移到 12 罚渐,所以 c存放位置為 (12 - 15)
    short d;  //  長(zhǎng)度為2 offset: 16  16是2的整數(shù)倍,所以 d存放位置為 (16 - 17)
}struct1;

3. 最終數(shù)據(jù)成員的整體內(nèi)存占用位置為 (0 - 17)驯妄,18個(gè)字節(jié)荷并。18不是基準(zhǔn) 8 的整數(shù)倍,因此填充到24.

最終 sizeof(struct1) 的大小為 24

如果我們稍微調(diào)整下數(shù)據(jù)順序:

struct Struct2 {
    double a; // 8
// 這里調(diào)整了 b青扔,c的順序
    int b;    // 4
    char c;   // 1
    short d;  // 2
}struct2;

1. 最長(zhǎng)的元素是double源织,基準(zhǔn)為8
2.
struct Struct2 {
    double a; // 長(zhǎng)度為8 offset:0,0是8的整數(shù)倍微猖,所以 a存放位置為 (0 - 7)
    int b;   //  長(zhǎng)度為4 offset: 8  8是 4的整數(shù)倍谈息,所以 b存放位置為 (8 - 11)
    char c;    //  長(zhǎng)度為1 offset:12  12是1的整數(shù)倍,所以 c存放位置為 (12)
    short d;  //  長(zhǎng)度為2 offset: 13  13不是2的整數(shù)倍励两,offset后移到 14 所以 d存放位置為 (14 - 15)
}struct2;

3. 最終數(shù)據(jù)成員的整體內(nèi)存占用位置為 (0 - 15)黎茎,16個(gè)字節(jié)囊颅。16是基準(zhǔn) 8 的整數(shù)倍当悔,因此不需要填充。

最終 sizeof(struct2) 的大小為 16

成員為數(shù)組的情況:

內(nèi)存對(duì)齊原則 ( ex1):

  1. 找到最大的基礎(chǔ)類(lèi)型成員 , 將其內(nèi)存長(zhǎng)度作為基準(zhǔn) (如果成員為數(shù)組踢代,基準(zhǔn)不按數(shù)組總長(zhǎng)盲憎,而是按照數(shù)組元素類(lèi)型來(lái)計(jì)算)
struct Struct3 {
    char a; // 1 (0)
    int b[2]; // b0 b1
    double c; //8
}struct3;

1. 最長(zhǎng)的元素是double,基準(zhǔn)為8
2.
struct Struct3 {
    char a; // 長(zhǎng)度為1 offset:0 0是1的整數(shù)倍胳挎,所以 a存放位置為 (0)
    int b[2]; // b0  長(zhǎng)度為4  0ffset:1  1不是4的整數(shù)倍饼疙,b0的offest后移到4,所以 b0存放位置為 (4 - 7)b1存放位置為 (8 - 11)
   double c; //長(zhǎng)度為8 offset: 12 12不是8的整數(shù)倍慕爬,offset后移到 16 所以 d存放位置為 (16 - 23)
}struct3;

3. 最終數(shù)據(jù)成員的整體內(nèi)存占用位置為 (0 - 23)窑眯,24個(gè)字節(jié)屏积。24是基準(zhǔn) 8 的整數(shù)倍,因此不需要填充磅甩。

最終 sizeof(struct3) 的大小為 24

其實(shí)數(shù)組寫(xiě)法很類(lèi)似下面的寫(xiě)法:

struct Struct3 {
    char a; 
    int b0;
    int b1;
    double c;
}struct3;

只要調(diào)整對(duì)了數(shù)組第一個(gè)元素的offset炊林,數(shù)組后續(xù)元素自然可以對(duì)齊。

成員為struct的情況:

  1. 找到最大的基礎(chǔ)類(lèi)型成員 , 將其內(nèi)存長(zhǎng)度作為基準(zhǔn) (如果成員為struct卷要,基準(zhǔn)不按子struct總長(zhǎng)渣聚,而是max(子struct基準(zhǔn),剩余成員內(nèi)存長(zhǎng)度))
  2. 每個(gè)成員的offset僧叉,需要是成員自己類(lèi)型的整數(shù)倍 (如果成員為struct, 只需是 成員struct 基準(zhǔn)的整數(shù)倍而不是總長(zhǎng)的整數(shù)倍)
struct Struct1 {
    double a; // 8
    char b;   // 1
    int c;    // 4
    short d;  // 2
}struct1;


struct Struct4 {
    int b;   // 4 // (0-3)
    char c;    // 1 //  (4)
    struct Struct1 s1; // a:8 (8 - 15) b:1 (16) c:4 (20 - 23) d:2 (24-25) (8 - 25) 18字節(jié) ->
    short d;  // 2 // 38 (36 - 37)
}struct4;

1. Struct1的基準(zhǔn)為8奕枝,除Struct1 s1外,Struct4最長(zhǎng)的元素是int 長(zhǎng)為4瓶堕,基準(zhǔn)為max(8隘道,4) = 8

2. 

struct Struct4 {
    int b;   // 4 // offset:0 ,存放位置: (0-3)
    char c;    // 1 //  offset:4捞烟,存放位置: (4)
    struct Struct1 s1; 
/**  a: 長(zhǎng)度: 8 offset:5 -> 8  存放位置: (8 - 15)
      b:長(zhǎng)度: 1  offset:16  存放位置:(16)
      c: 長(zhǎng)度: 4 offset:17 -> 20 存放位置: (20 - 23) 
      d: 長(zhǎng)度:  2 offset:24  存放位置: (24-25) 
      s1 總體位置:(8 - 25) 18字節(jié) -> 填充 (8 - 31)24字節(jié)
**/
    short d;  // 2 // offset:32薄声,存放位置: (32 - 33)
}struct4;

3. 總體位置 (0 - 33) 長(zhǎng)度為 34,不是8的倍數(shù)题画,填充到 40 

最終 sizeof(struct4) 的大小為 40

附表:

  1. 基礎(chǔ)數(shù)據(jù)表


    image.png

2.內(nèi)存分布查看方法:

po &struct4 -> 0x00000001014cc600

x/8gx 0x00000001014cc600
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末默辨,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子苍息,更是在濱河造成了極大的恐慌缩幸,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件竞思,死亡現(xiàn)場(chǎng)離奇詭異表谊,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)盖喷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)爆办,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人课梳,你說(shuō)我怎么就攤上這事距辆。” “怎么了暮刃?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵跨算,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我椭懊,道長(zhǎng)诸蚕,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮背犯,結(jié)果婚禮上坏瘩,老公的妹妹穿的比我還像新娘。我一直安慰自己漠魏,他們只是感情好桑腮,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著蛉幸,像睡著了一般破讨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上奕纫,一...
    開(kāi)封第一講書(shū)人閱讀 49,144評(píng)論 1 285
  • 那天提陶,我揣著相機(jī)與錄音,去河邊找鬼匹层。 笑死隙笆,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的升筏。 我是一名探鬼主播撑柔,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼您访!你這毒婦竟也來(lái)了铅忿?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤灵汪,失蹤者是張志新(化名)和其女友劉穎檀训,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體享言,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡峻凫,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了览露。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片荧琼。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖差牛,靈堂內(nèi)的尸體忽然破棺而出命锄,到底是詐尸還是另有隱情,我是刑警寧澤多糠,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布累舷,位于F島的核電站浩考,受9級(jí)特大地震影響夹孔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一搭伤、第九天 我趴在偏房一處隱蔽的房頂上張望只怎。 院中可真熱鬧,春花似錦怜俐、人聲如沸身堡。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)贴谎。三九已至,卻和暖如春季稳,著一層夾襖步出監(jiān)牢的瞬間擅这,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工景鼠, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留仲翎,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓铛漓,卻偏偏與公主長(zhǎng)得像溯香,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子浓恶,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345