資源描述:
《詳解結構體、類等內存字節(jié)對齊》由會員上傳分享,免費在線閱讀,更多相關內容在應用文檔-天天文庫。
1、先說個題外話:早些年我學C程序設計時,寫過一段解釋硬盤MBR分區(qū)表的代碼,對著磁盤編輯器怎么看,怎么對,可一執(zhí)行,結果就錯了。當時調試也不太會,又根本沒聽過結構體對齊這一說,所以,問題解決不了,好幾天都十分糾結。后來萬般無奈請教一個朋友,才獲悉可能是結構體對齊的事,一查、一改,果真如此。?問題是解決了,可網上的資料多數只提到內存對齊是如何做的,卻鮮有提及為什么這樣做(即使提,也相當簡單)。筆者是個超級健忘者,很難機械式的記住這些破規(guī)則,于是仔細想了想,總算明白了原因,這樣,這些對齊的規(guī)則也就不會再輕易忘記了。????不光結構體存在內存對齊一說,類
2、(對象)也如此,甚至于所有變量在內存中的存儲也有對齊一說(只是這些對程序員是透明的,不需要關心)。實際上,這種對齊是為了在空間與復雜度上達到平衡的一種技術手段,簡單的講,是為了在可接受的空間浪費的前提下,盡可能的提高對相同運算過程的最少(快)處理。先舉個例子:?假設機器字長是32位的(即4字節(jié),下面示例均按此字長),也就是說處理任何內存中的數據,其實都是按32位的單位進行的。現在有2個變量:???1.char?A;?2.int?B;????假設這2個變量是從內存地址0開始分配的,如果不考慮對齊,應該是這樣存儲的(見下圖,以intel上的littl
3、eendian為例,為了形象,每16個字節(jié)分做一行,后同):??因為計算機的字長是4字節(jié)的,所以在處理變量A與B時的過程可能大致為:??A:將0x00-0x03共32位讀入寄存器,再通過左移24位再右移24位運算得到a的值(或與0x000000FF做與運算)??B:將0x00-0x03這32位讀入寄存器,通過位運算得到低24位的值;再將0x04-0x07這32位讀入寄存器,通過位運算得到高8位的值;再與最先得到的24位做位運算,才可得到整個32位的值。??上面敘述可知,對a的處理是最簡處理,可對b的處理,本身是個32位數,處理的時候卻得折成2部分
4、,之后再合并,效率上就有些低了。??想解決這個問題,就需要付出幾個字節(jié)浪費的代價,改為下圖的分配方式:??按上面的分配方式,A的處理過程不變;B卻簡單得多了:只需將0x04-0x07這32位讀入寄存器就OK了。??我們可以具體談結構體或類成員的對齊了:??結構體在編譯成機器代碼后,其實就沒有本身的集合概念了,而類,實際上是個加強版的結構體,類的對象在實例化時,內存中申請的就是一些變量的空間集合(類似于結構體,同時也不包含函數指針)。這些集合中的每個變量,在使用中,都需要涉及上述的加工原則,自然也就需要在效率與空間之間做出權衡。??為了便捷加工連續(xù)
5、多個相同類型原始變量,同時簡化原始變量尋址,再匯總上述最少處理原則,通??梢詫⒃甲兞康拈L度做為針對此變量的分配單位,比如內存可用64個單元,如果某原始變量長度為8字節(jié),即使機器字長為4字節(jié),分配的時候也以8字節(jié)對齊(看似IO次數是相同的),這樣,尋址、分配時,均可以按每8字節(jié)為單位進行,簡化了操作,也可以更高效。??系統默認的對齊規(guī)則,追求的至少兩點:1、變量的最高效加工2、達到目的1的最少空間???舉個例子,一個結構體如下:?1.//bywww.datahf.netzhangyu2.typedef?struct?T3.{?4.????char
6、?c;//本身長度1字節(jié)?5.????__int64?d;?//本身長度8字節(jié)6.????int?e;?//本身長度4字節(jié)7.????shortf;?//本身長度2字節(jié)8.????char?g;?//本身長度1字節(jié)9.????short?h;?//本身長度2字節(jié)10.};???假設定義了一個結構體變量C,在內存中分配到了0x00的位置,顯然:??對于成員C.c?無論如何,也是一次寄存器讀入,所以先占一個字節(jié)。??對于成員C.d?是個64位的變量,如果緊跟著C.c存儲,則讀入寄存器至少需要3次,為了實現最少的2次讀入,至少需要以4字節(jié)對齊;同時對于
7、8字節(jié)的原始變量,為了在尋址單位上統一,則需要按8字節(jié)對齊,所以,應該分配到0x08-0xF的位置。??對于成員C.e?是個32位的變量,自然只需滿足分配起始為整數個32位即可,所以分配至0x10-0x13。??對于成員C.f?是個16位的變量,直接分配在0x14-0x16上,這樣,反正只需一次讀入寄存器后加工,邊界也與16位對齊。??對于成員C.g?是個8位的變量,本身也得一次讀入寄存器后加工,同時對于1個字節(jié)的變量,存儲在任何字節(jié)開始都是對齊,所以,分配到0x17的位置。??對于成員C.h?是個16位的變量,為了保證與16位邊界對齊,所以,分
8、配到0x18-0x1A的位置。??分配圖如下(還不正確,耐心讀下去):??結構體C的占用空間到h結束就可以了嗎?我們找個示例:如果定義一