#字節(jié)對齊

[TOC]

什么是字節(jié)對齊(可以跳過)

現(xiàn)代計算機中內(nèi)存空間都是按照字節(jié)(byte)劃分的都哭,從理論上講似乎對任何類型的變量的訪問可以從任何地址開始照卦,但實際情況是在訪問特定變量的時候經(jīng)常在特定的內(nèi)存地址訪問儡蔓,這就需要各類型數(shù)據(jù)按照一定的規(guī)則在空間上排列,而不是順序地一個接一個地排放,這就是對齊.

字節(jié)對齊的好處(可以跳過)

為了提高效率,計算機從內(nèi)存中取數(shù)據(jù)是按照一個固定長度的斧吐。以32位機為例,它每次取32個位仲器,也就是4個字節(jié)(每字節(jié)8個位)煤率。字節(jié)對齊有什么好處?以int型數(shù)據(jù)為例乏冀,如果它在內(nèi)存中存放的位置按4字節(jié)對齊蝶糯,也就是說1個int的數(shù)據(jù)全部落在計算機一次取數(shù)的區(qū)間內(nèi),那么只需要取一次就可以了.

如何對齊

通常辆沦,我們寫程序的時候昼捍,不需要考慮對齊問題,編譯器會替我們選擇適合目標平臺的對齊策略肢扯。但是妒茬,正因為我們一般不需要關心這個問題,所以鹃彻,如果編輯器對數(shù)據(jù)存放做了對齊郊闯,而我們不了解的話,常常會對一些問題感到迷惑蛛株。最常見的就是struct數(shù)據(jù)結構的sizeof結果,例如:

typedef struct
{
    char  member1;
    short member2;
    int   member3;
}Family;

//打印長度
NSLog(@"Family size is %zd",sizeof(Family));

//輸出結果
2016-07-22 15:34:29.081 Study[14587:5575156] Family size is 8

//下面我們更換一下成員變量位置,看看有什么效果

typedef struct
{
    char  member1;
    int   member3;
    short member2;
}Family;

//打印長度
NSLog(@"Family size is %zd",sizeof(Family));

//輸出結果

2016-07-22 15:36:25.126 Study[14591:5575689] Family size is 12

那么問題來了,兩個結構體的成員變量只是改變了下順序育拨,為什么占用的內(nèi)存大小不同呢谨履?

對齊原則:

  • char 偏移量必須為sizeof(char) 即1的倍數(shù),可以任意地址開始存儲
  • short 偏移量必須為sizeof(short) 即2的倍數(shù),只能從0,2,4...等2的倍數(shù)的地址開始存儲
  • int 偏移量必須為sizeof(int) 即4的倍數(shù),只能從0,4,8...等4的倍數(shù)的地址開始存儲
  • float 偏移量必須為sizeof(float) 即4的倍數(shù),只能從0,4,8...等4的倍數(shù)的地址開始存儲
  • double 偏移量必須為sizeof(double)即8的倍數(shù),只能從0,8,16...等地址開始存儲

根據(jù)以上原則,我們來分析:

typedef struct
{
    char  member1;
    short member2;
    int   member3;
}Family;

  • 這個結構體:member1占一個字節(jié),即 存儲位置為 0
  • member2占兩個字節(jié),根據(jù)上面原則,開始存儲地址應該是2的倍數(shù),即 2~3
  • member3占4個字節(jié),根據(jù)原則,開始存儲地址是4的倍數(shù),即 4~7
  • 總共占用了0 ~ 7 共8個字節(jié).
    內(nèi)存存儲圖為:


    Paste_Image.png

下面分析:

typedef struct
{
    char  member1;
    int   member3;
    short member2;
}Family;

  • 這個結構體:member1占一個字節(jié),即 0
  • member2占4個字節(jié),根據(jù)上面原則,開始存儲地址應該是4的倍數(shù),即 4~7
  • member3占2個字節(jié),根據(jù)上面原則,開始存儲地址是2的倍數(shù),即 8 ~ 9
    總共占用了0 ~ 9 應該是10個字節(jié),但為什么實際卻是12個字節(jié)呢 ?
    因為默認對齊方式是4字節(jié)(至于為什么,往下看),也就是說,總長度必須是4的倍數(shù),因此長度既要大于10,還要是4的倍數(shù),那就是12了.
    內(nèi)存結構圖為:


    Paste_Image.png

結構體如何設定字節(jié)對齊

  • 當未明確指定時,以結構體中最長的成員的長度為其有效值,上面的兩個結構體都是int類型最長,也就是4字節(jié)對齊

  • 結構體作為成員:如果一個結構里有某些結構體成員,則結構體成員要從其內(nèi)部最大元素大小的整數(shù)倍地址開始存儲.(struct a里存有struct b,b里有char,int ,double等元素,那b應該從8的整數(shù)倍開始存儲.)

  • 結構體的總大小,也就是sizeof的結果,必須是其內(nèi)部最大成員的整數(shù)倍.不足的要補齊.

  • 當用#pragma pack(n)指定時熬丧,以n和結構體中最長的成員的長度中較小者為其值.

  • 用#pragma pack()為還原字節(jié)對齊為默認值.

  • attribute ((packed)) 1字節(jié)對齊,此時結構體的長度就是各成員變量長度之和.

例如:

pragma pack 的用法

struct A {
    int   a;
    char  b;
    short c;
};

struct B {
    char  b;
    int   a;
    short c;
};

#pragma pack (2) /*指定按2字節(jié)對齊*/
struct C {
    char  b;
    int   a;
    short c;
};
#pragma pack () /*取消指定對齊笋粟,恢復缺省對齊*/



#pragma pack (1) /*指定按1字節(jié)對齊*/
struct D {
    char  b;
    int   a;
    short c;
};
#pragma pack ()/*取消指定對齊,恢復缺省對齊*/

//計算所占字節(jié)
int s1=sizeof(struct A);
    int s2=sizeof(struct B);
    int s3=sizeof(struct C);
    int s4=sizeof(struct D);
    
    printf("%d\n",s1);
    printf("%d\n",s2);
    printf("%d\n",s3);
    printf("%d\n",s4);
//輸出結果:
8
12
8
7

attribute ((packed))的用法:
讓指定的結構結構體按照 1 字節(jié)對齊,例如:

//不加packed修飾
typedef struct {
    char    version;
    int16_t sid;
    int32_t len;
    int64_t time;
} Header;

//計算長度
NSLog(@"size is %zd",sizeof(Header));
輸出結果為:
2016-07-22 11:53:47.728 Study[14378:5523450] size is 16

可以看出,默認系統(tǒng)是按照4字節(jié)對齊

//加packed修飾
typedef struct {
    char    version;
    int16_t sid;
    int32_t len;
    int64_t time;
}__attribute__ ((packed)) Header;

//計算長度
NSLog(@"size is %zd",sizeof(Header));
輸出結果為:
2016-07-22 11:57:46.970 Study[14382:5524502] size is 15

用packed修飾后,變?yōu)?字節(jié)對齊,這個常用于與協(xié)議有關的網(wǎng)絡傳輸中.

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市害捕,隨后出現(xiàn)的幾起案子绿淋,更是在濱河造成了極大的恐慌,老刑警劉巖尝盼,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吞滞,死亡現(xiàn)場離奇詭異,居然都是意外死亡盾沫,警方通過查閱死者的電腦和手機裁赠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赴精,“玉大人佩捞,你說我怎么就攤上這事±儆矗” “怎么了一忱?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長谭确。 經(jīng)常有香客問我掀潮,道長,這世上最難降的妖魔是什么琼富? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任仪吧,我火速辦了婚禮,結果婚禮上鞠眉,老公的妹妹穿的比我還像新娘薯鼠。我一直安慰自己,他們只是感情好械蹋,可當我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布出皇。 她就那樣靜靜地躺著,像睡著了一般哗戈。 火紅的嫁衣襯著肌膚如雪郊艘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天唯咬,我揣著相機與錄音纱注,去河邊找鬼。 笑死胆胰,一個胖子當著我的面吹牛狞贱,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蜀涨,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼瞎嬉,長吁一口氣:“原來是場噩夢啊……” “哼蝎毡!你這毒婦竟也來了?” 一聲冷哼從身側響起氧枣,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤沐兵,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后便监,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體扎谎,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年茬贵,在試婚紗的時候發(fā)現(xiàn)自己被綠了簿透。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡解藻,死狀恐怖老充,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情螟左,我是刑警寧澤啡浊,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站胶背,受9級特大地震影響巷嚣,放射性物質發(fā)生泄漏。R本人自食惡果不足惜钳吟,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一廷粒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧红且,春花似錦坝茎、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至壁酬,卻和暖如春次酌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背舆乔。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工岳服, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蜕煌。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓派阱,卻偏偏與公主長得像,于是被迫代替她去往敵國和親斜纪。 傳聞我的和親對象是個殘疾皇子贫母,可洞房花燭夜當晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容

  • @[c++|struct] 今天在編程中碰到一個坑,搞的調試了半天盒刚,最后發(fā)現(xiàn)程序中在寫數(shù)據(jù)和讀取數(shù)據(jù)時結構體定義不...
    drybeans閱讀 3,581評論 1 11
  • 4.3:新增class的相關內(nèi)容 今天看到一個題目: 最開始簡單的理解為腺劣,每個數(shù)據(jù)的size之和就是偏移量。因為偏...
    AwesomeAshe閱讀 723評論 0 0
  • 1. 對齊 需要各類型數(shù)據(jù)按照一定的規(guī)則在內(nèi)存空間上排列因块,而不是順序的排放橘原,這就是對齊。 2. 對齊的原因 最常見...
    Sheldor936閱讀 364評論 0 0
  • (字節(jié)對齊的實現(xiàn)細節(jié)和編譯器有關) 1. 基本概念 字節(jié)對齊:計算機存儲系統(tǒng)中以Byte為單位存儲數(shù)據(jù)击孩,不同數(shù)據(jù)類...
    安然_fc00閱讀 2,865評論 0 1
  • 通過一段代碼來描述內(nèi)存對齊的現(xiàn)象癌幕。 上述代碼打印出來的結果為:24,16 為什么相同的結構體兆蕉,只是交換了變量 ab...
    豆瓣菜閱讀 6,682評論 5 26