結構體拾遺補缺1:內存對齊與sizeof

一、結構體字節對齊  
    爲什麼需要字節對齊?計算機組成原理教導我們這樣有助於加快計算機的取數速度,否則就得多花指令週期了。爲此,編譯器默認會對結構體進行處理(實際上其它地方的數據變量也是如此),讓寬度爲2的基本數據類型(short等)都位於能被2整除的地址上,讓寬度爲4的基本數據類型(int等)都位於能被4整除的地址上,以此類推。這樣,兩個數中間就可能需要加入填充字節,所以整個結構體的sizeof值就增長了。

    字節對齊的細節和編譯器實現相關,但一般而言,滿足三個準則
   1) 結構體變量的首地址能夠被其最寬基本類型成員的大小所整除;
    備註:編譯器在給結構體開闢空間時,首先找到結構體中最寬的基本數據類型,然後尋找內存地址能被該基本數據類型所整除的位置,作爲結構體的首地址。將這個最寬的基本數據類型的大小作爲上面介紹的對齊模數。
    2) 結構體每個成員相對於結構體首地址的偏移量(offset)都是成員大小的整數倍,如有需要編譯器會在成員之間加上填充字節(internal adding);
    備註:爲結構體的一個成員開闢空間之前,編譯器首先檢查預開闢空間的首地址相對於結構體首地址的偏移是否是本成員的整數倍,若是,則存放本成員,反之,則在本成員和上一個成員之間填充一定的字節,以達到整數倍的要求,也就是將預開闢空間的首地址後移幾個字節。
    3) 結構體的總大小爲結構體最寬基本類型成員大小的整數倍,如有需要編譯器會在最末一個成員之後加上填充字節(trailing padding)。
    備註:結構體總大小是包括填充字節,最後一個成員滿足上面兩條以外,還必須滿足第三條,否則就必須在最後填充幾個字節以達到本條要求。
   故:用sizeof()求結構體字節大小時,必須嚴格遵守上面的3個準則。

    我們來看一個例子:
    typedef struct ms1
    {
       char a;
       int b;
    } MS1;
    假設MS1按如下方式內存佈局(本文所有示意圖中的內存地址從左至右遞增):
       _____________________________
       |       |                   |
       |   a   |        b          |
       |       |                   |
       +---------------------------+
Bytes:   

發佈了10 篇原創文章 · 獲贊 5 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章