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

目錄

  • 內(nèi)存對(duì)齊規(guī)則
  • 對(duì)齊系數(shù)
  • 面試題演練

一、內(nèi)存對(duì)齊規(guī)則 (關(guān)于面試題中結(jié)構(gòu)體內(nèi)存對(duì)齊計(jì)算總結(jié)

  • 1.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)行

  • 1.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)行。

1.3:結(jié)構(gòu)體作為成員:

如果一個(gè)結(jié)構(gòu)里有某些結(jié)構(gòu)體成員,則結(jié)構(gòu)體成員要從其內(nèi)部最大元素大小的整數(shù)倍地址開(kāi)始存儲(chǔ)。


二、#pragma pack(n) 對(duì)齊系數(shù)

????????每個(gè)特定平臺(tái)上的編譯器都有自己的默認(rèn)“對(duì)齊系數(shù)”(也叫對(duì)齊模數(shù))。程序員可以通過(guò)預(yù)編譯命令#pragma pack(n),n=1,2,4,8,16來(lái)改變這一系數(shù),其中的n就是你要指定的“對(duì)齊系數(shù)”。
????????其中,Xcode 中默認(rèn)為#pragma pack(8)


三、演練

演練1、

struct StructOne { 
                 長(zhǎng)度        對(duì)齊      偏移     區(qū)間
    char   a;       1  < 8     1         0      [0]     
    double b;       8  = 8     8         8      [8,  15]
    int    c;       4  < 8     4         16     [16, 19]
    short  d;       2  < 8     2         20     [20, 21]
} MyStruct1;

解讀:
1、數(shù)據(jù)成員的對(duì)齊按照#pragma pack-8和自身長(zhǎng)度中比較小的那個(gè)進(jìn)行
-- char a 的自身長(zhǎng)度為 1, 1 < 8, 按 1 對(duì)齊

2、第一個(gè)數(shù)據(jù)成員放在offset為0的地方
-- char a 的偏移為 1

3、整體對(duì)齊系數(shù) = min((max(int,short,char,double), 8) = 8,
   將 21 提升到 8 的倍數(shù),則為 24,所以最終結(jié)果為 24 個(gè)字節(jié)

整體對(duì)齊系數(shù) = min((max(int,short,char,double), 8) = 8,將21提升到8的倍數(shù),則為24,所以最終結(jié)果為24個(gè)字節(jié)

演練2、
struct StructOne { 
                 長(zhǎng)度        對(duì)齊      偏移     區(qū)間
    double b;       8  = 8     8         0      [0,   7]     
    char   a;       1  < 8     1         8      [8]
    short  d;       2  < 8     2         10     [10, 11]
    int    c;       4  < 8     4         12     [12, 15]
} MyStruct1;

解讀:
這個(gè)和演練1不同的是short d,由于它是 2 對(duì)齊,上一個(gè)偏移量為 9,
9不是2的整數(shù)倍,所以向上取整,到10,"short b" 偏移為10

留給大家自己算的
struct x_ {
    char  a;      // 1 byte
    int   b;      // 4 bytes
    short c;      // 2 bytes
    char  d;      // 1 byte
} MyStruct1;

struct y_ {
    int   b;      // 4 bytes
    char  a;      // 1 byte
    char  d;      // 1 byte
    short c;      // 2 bytes
} MyStruct2;

NSLog(@"%lu,%lu", sizeof(MyStruct1), sizeof(MyStruct2));
12---8
struct StructOne {
    char   a;      // 1字節(jié)
    double b;      // 8字節(jié)
    int    c;      // 4字節(jié)
    short  d;      // 2字節(jié)
} MyStruct1;

struct StructTwo {
    double b;       // 8字節(jié)
    char   a;       // 1字節(jié)
    short  d;       // 2字節(jié)
    int    c;       // 4字節(jié)
} MyStruct2;
NSLog(@"%lu---%lu--", sizeof(MyStruct1), sizeof(MyStruct2));

2019-01-16 08:52:13.830861+0800 size[1031:10969] 24---16--
復(fù)雜一點(diǎn)演練(結(jié)構(gòu)體包含結(jié)構(gòu)體-明天解讀)
struct EE
{                       長(zhǎng)度        對(duì)齊      偏移     區(qū)間
    int     a;            4 < 8       4        0      [0, 3]
    char    b;            1 < 8       1        4      [4] 
    short   c;            2 < 8       2        6      [6, 7]
 //結(jié)構(gòu)體內(nèi)部最大元素為int ,由于偏移量為8剛好是4的整數(shù)倍,所以從8開(kāi)始存放接下來(lái)的struct FF
    struct FF    
    {
        int   a1;         4 < 8       4        8      [8, 11]
        char  b1;         1 < 8       1        12     [12]      
        short c1;         2 < 8       2        14     [14, 15]    
        char  d1;         1 < 8       1        16     [16] 
    };
    // 整體對(duì)齊:min(max(int, char, short), 8) = 4, 將內(nèi)存大小由17補(bǔ)齊到4的整數(shù)倍20
    char d;               1 < 8       1        21     [21] 
    // 整體對(duì)齊系數(shù) = min((max(int,short,char), 8) = 4,將內(nèi)存大小由21補(bǔ)齊到4的整數(shù)倍24
};
----24
struct B {           長(zhǎng)度        對(duì)齊      偏移     區(qū)間
    char   e[2];        1 < 8      2        0      [0, 1]   
    short  h;           2 < 8      2        2      [2, 3]  
 //結(jié)構(gòu)體內(nèi)部最大元素為double ,由于偏移量為8剛好是4的整數(shù)倍,所以從8開(kāi)始存放接下來(lái)的struct A
    struct A {  
        int    a;        4 < 8      4        8      [8, 11] 
        double b;        8 = 8      8        16     [16, 23]
        float  c;        4 < 8      4        24     [24, 27]
    };
        // 整體對(duì)齊系數(shù) = min((max(int,double ,float), 8) = 8
        // 將內(nèi)存大小由28補(bǔ)齊到8的整數(shù)倍32,∴ result = 32
};

----32

參考文章:
iOS 關(guān)于面試題中結(jié)構(gòu)體內(nèi)存對(duì)齊、類內(nèi)存對(duì)齊計(jì)算總結(jié)
http://www.itdecent.cn/p/a371e2613ec8
http://www.itdecent.cn/p/3294668e2d8c

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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