本文所有內容在建立在乙個前提下:使用vc編譯器。著重點在於:vc的記憶體對齊準則;同樣的資料, 不同的排列有不同的大小,另外在有虛函式或虛擬繼承情況下又有如何影響?
對於一台32位的機器來說如何才能發揮它的最佳訪問效率呢?當然是每次都讀4位元組(32bit), 這樣才可以讓它的bus處於最高效率。實際上它也是這麼做的,即使你只需要乙個位元組,它也是 讀乙個機器字長(這兒是32bit)。更重要的是,有的機器在訪問或儲存資料的時候它要求資料 必須是對齊的,何謂對齊?它要求資料的位址從4的倍數開始,如若不然,它就報錯。還有的機 器它雖然不報錯,但對於乙個類似int變數,假如它橫跨乙個邊界的兩端,那麼它將要進行兩次 讀取才能獲得這個int值。比方它儲存在位址為2~5的四個位元組中,那麼要讀取這個int,將要 進行兩次讀取,第一次讀取0~3四個位元組,第二次讀取4~7四個位元組。但是如果我們把這個整 形的起始位址調整到0,4,8…呢?一次訪問就夠了!這種調整就是記憶體對齊了。我們也可以依次 類推到16位或64位的機器上。
對於32位的機器來說,它當然最渴望它的資料的大小都是4 byte或者4的倍數byte,這樣它就能 最有效率的訪問資料,當然如果資料小於4byte,那也是沒問題的。那麼編譯器要做的便是盡量滿 足這個要求。
這兩天我斷續對vc做了一些實驗,並總結如下三條準則,你要明白的是這並非來自微軟的官方文 檔,但我自以為這些準則或許不全但應該都是正確的:
對於類t:
class將其sizeof輸出後的大小為16,其記憶體布局如圖t.變數c從偏移量為0開始儲存,而整形i第乙個 符號條件的偏移量為4,double型d的第乙個符號條件的為8。整個物件的大小為16,不需要再進 行額外的對齊。t;
圖t(類t 的記憶體布局) :
再看類l,它與t儲存同樣型別的資料,僅僅是順序不同罷了,那麼它sizeof輸出的大小是多少呢?
類l:
class圖l(類l的布局)l;
我得出了這樣一條並不權威的結論,因為我還沒聽有人這樣說過:在宣告資料成員的時候,將 最大位元組數的變數放在最前面3
,切忌不要將大小差距很大的型別交替宣告。
前面的例項只涉及前兩條準則,現在我們來看看第三條的兩個例項:
classx;y的大小為:a佔乙個位元組,vbcpoint(我稱他為虛基類指標)佔四個位元組。我們不論a與vbcpoint 的位置如何擺放,如果將vbcpoint等同於乙個成員資料來看的話,sizeof(y)都應該為8.實際上 它是5!就我目前的水平,我只能先將其解釋為vbcpoint不參與對齊。classy:
virtual
public
x{};
對於vptr這個問題則不存在:
classsizeof(x)的大小確實為8.x;}
用#pragma pack(n)改變規定對齊量試試
規定對齊量:實際上並沒有這麼乙個名詞,是我為了方便而造出來的。在vc中這個「規定對齊量」會有乙個預設值,這個預設值一般為8,我原來一直以為這個值以為是4,至於它為什麼為8,我現在還不知道。。我們也可以通過#pargma pack(n)來規定這個值,目前n可以為1,2,4,8,16。 ↩
這個起始位置指的是相對於結構體(類)來說的。 ↩
提出從小到大可能好些,雖然沒有給出有說服力的理由,但卻使我無比困惑,我當時雖然認為從大到小的排列更有優勢,但卻實在想不出乙個例項能使得它優於從小到大排列的。不過最終我擊垮了自己的理由,在繼承狀況下從大到小排列很容易被打破,比方,基類的成員為乙個char,繼承類的成員為double,int,char雖然基類和繼承類都是按從大到小的順序排列的,但是繼承類的記憶體布局最終會使char,double,int,char,此時既不能避免成員對齊,又導致後面的結構體對齊。暫時獲得的最終結果是從小到大排列是更好的一種排列方式。(2011/12/31增補) ↩
-----------------
class x{};
class y: virtual public x;
sizeof(y)得到的卻是8
在vs2008上試的。
C語言 結構體與記憶體對齊準則簡單理解
平時基本不涉及這個問題,被問起才發現沒那麼簡單。一,結構體 記憶體中所有型別位元組之和 includestruct icd struct cdi struct merge int main void 1.首先要找到結構題中所佔位元組數最大的型別,icd中最大位元組數為8,則int為4,char為1,...
記憶體對齊 記憶體對齊規則解釋 記憶體對齊原理
一 記憶體對齊的原因 我們都知道計算機是以位元組 byte 為單位劃分的,理論上來說cpu是可以訪問任一編號的位元組資料的,我們又知道cpu的定址其實是通過位址匯流排來訪問記憶體的,cpu又分為32位和64位,在32位的cpu一次可以處理4個位元組 byte 的資料,那麼cpu實際定址的步長就是4個...
struct記憶體對齊 gcc與VC的差別
記憶體對齊是編譯器為了便於cpu快速訪問而採用的一項技術,對於不同的編譯器有不同的處理方法。win32平台下的微軟vc編譯器在預設情況下採用如下的對齊規則 任何基本資料型別t 的對齊模數就是t的大小,即sizeof t 比如對於double型別 8位元組 就要求該型別資料的位址總是8的倍數 而cha...