文章原文在我的個人博客
為什么會有內存對齊?
為了訪問未對齊的內存,處理器需要作兩次內存訪問;而,對齊訪問僅需要一次訪問。
對齊參數
32位系統中,默認4字節對齊(32位系統CPU字長是4字節)
- 在Windows(32)/VC6.0下各種數據類型的變量的自身對齊參數就是該數據類型變量所占字節數的大小
- 在Linux(32)/GCC下double類型下的對齊參數為4
- Linux(32)/GCC下如果該數據類型的長度沒有超過CPU的字長,則以該數據類型變量的長度作為自身對齊參數
- 如果超過了CPU字長,則自身對齊參數為CPU字長
字節對齊原則
- 結構體每個成員相對結構體首地址的偏移量(offset)是對齊參數(此對齊參數是取每個變量自身對齊參數和系統對齊參數兩者中較小的一個)的整數倍,如果有需要會在每個成員之間填充字節
- 編譯器在為結構體成員開辟空間時,首先檢查預開辟空間的地址相對于結構體首地址的偏移量是否為對齊參數的整數倍,若是,則存放該成員,否則,反之
- 結構體變量所占空間的大小是對齊參數大小的整數倍,如有需要會在最后一個成員末尾填充若干字節使得所占空間是對齊參數 (對結構體中所有變量的對齊參數的最大值和系統默認對齊參數#pragma pack(n)比較,較小者作為對齊參數)的整數倍
static修飾的變量所占空間沒有被算入,因為其存儲在.bss段/.data段
內存對齊的關鍵字
GCC推薦的對齊指令
__attribute__((packed)) // 一字節對齊使用時,直接接放在進行內存對齊的類型定義后面,其作用范圍為使用該類型定義的變量
__attribute__((aligned(n))) // 用法同上,使整個結構體進行n字節的對齊(n為2的冪次方)
GCC支持但不推薦的對齊指令
#pragma pack(n) // 放在自定義字節對齊的數據結構開頭,指定編譯器對齊參數為n字節
定義結構體
#pragma pack() // 放在自定義字節對齊的數據結構結尾,取消指定對齊參數,恢復缺省參數