華清遠見嵌入式培訓中心
講師。記憶體是以位元組為單位編號,但一些硬體平台對某些特定型別的資料只能從某些特定位址開始,比如從偶位址開始。若不按照適合其平台的要求對資料存放進行對齊,會影響到效率。因此,在記憶體中,各型別的資料是按照一定的規則在記憶體中存放的,這就是本文要研究的對齊問題。
本文以gcc version 4.4.5,32位x86環境為例,來分析結構體中各成員如何進行對齊。
結構體對齊規則如下:
結構體的總長度:對齊在成員型別長度最大的值和pragma pack(value)指定值中較小的值上。
所謂「對齊在n上」,指定是「存放起始位址%n=0」
看下面幾個例子:
例1:
分析:此程式的測試環境,相當於pragma pack(4),
a 成員的起始位址是0xbfe8ff18,
char型別長度1,pragma pack(4),取小的1, 0xbfe8ff18%1=0,符合規則。
b成員,short型別長度2,pragma pack(4),取小的2,若存在位址0xbfe8ff19,則0xbfe8ff19%2餘數為1,不是0,所以只能空出乙個位元組,在0xbfe8ff1a位址存放。
c成員,int型別長度4,pragma pack(4),取小的4,若存在位址0xbfe8ff1a+2,即0xbfe8ff1c處,則0xbfe8ff1c%4餘數為0,符合規則。
這樣整個結構體,占用了記憶體的0xbfe8ff18~0xbfe8ff1f, 共8個位元組。結構體的總長度是要求「對齊在成員型別長度最大的值和pragma pack(value)指定值中較小的值上。」這裡是要求能被4除盡,8符合要求,所以sizeof(struct f)是8.
例2:
a成員的起始位址是0xbfe8ff18,
char型別長度1,pragma pack(4),取小的1, 0xbfbb41a8%1=0。
b成員,int型別長度4,pragma pack(2),取小的2,若存在位址0xbfbb41a9,則0xbfbb41a9%2餘數為1,不是0,所以只能空出乙個位元組,在0xbfbb41aa位址存放。
c成員,short型別長度2,pragma pack(2),取小的2,若存在位址0xbfbb41aa +4,即0xbfbb41ae處,則0xbfbb41ae %4餘數為0,符合規則。這樣整個結構體,占用了記憶體的0xbfbb41a8~0xbfbb41af, 共8個位元組。結構體的總長度是要求「對齊在成員型別長度最大的值和pragma pack(value)指定值中較小的值上。」這裡是要求能被2除盡,8符合要求,所以sizeof(struct f)是8.
例3:
具體的分析,不再重複,讀者可以和上面的例子做個比較,有了pragma pack(4)後,結構體的總長度,為12,不再是8。
android培訓
3g培訓
qt培訓
物聯網培訓
嵌入式學習
結構體對齊(記憶體對齊
有的時候,在腦海中停頓了很久的 顯而易見 的東西,其實根本上就是錯誤的。就拿下面的問題來看 structt 使用sizeof t 將得到什麼樣的答案呢?要是以前,想都不用想,在32位機中,int是4個位元組,char是1個位元組,所以t一共是5個位元組。實踐出真知,在vc6中測試了下,答案確實8個位...
記憶體對齊 結構體對齊
現在已知32位機器上各種資料型別的長度如下 char 1 有符號無符號同 short 2 有符號無符號同 int 4 有符號無符號同 long 4 有符號無符號同 float 4 double 8 重要規則 1,複雜型別中各個成員按照它們被宣告的順序在記憶體中順序儲存,第乙個成員的位址和整個型別的位...
結構體的記憶體對齊
原則一 結構體中元素是按照定義順序乙個乙個放到記憶體中去的,但並不是緊密排列的。從結構體儲存的首位址開始,每乙個元素放置到記憶體中時,它都會認為記憶體是以它自己的大小來劃分的,因此元素放置的位置一定會在自己寬度的整數倍上開始 以結構體變數首位址為0計算 原則二 在經過第一原則分析後,檢查計算出的儲存...