1樓:橡皮泥胖子
最近在看《深度探索C++物件模型》,根據第三章《Data語意學》的開頭,乙個struct/class的大小除了本身各個Non-static成員的大小外,由三部分決定:
1. 語言本身造成的overload,比如虛繼承和虛函式,需要額外存放指標在物件裡;
2. 編譯器對特殊情況的優化,如empty virtual base class之類的;
3. 記憶體對齊。
我估計很多類似的題目都是只考量第三點而已,所以下面就第三點展開,struct的記憶體對齊規則是怎樣的呢?
0.定義乙個型別Type的unit值:
1)如果Type是乙個內建型別,則unit(Type) = sizeof(Type),如unit(char) = 1;
2)如果Type是乙個struct,則unit(Type) = max(unit(non-static data member Type))。
舉個例子:
structAf
;};(假設在64位機器上,)其中unit(Inner) = max(sizeof(double), sizeof(char)) = 8,
而unit(A) = max(sizeof(char), sizeof(int), unit(Inner)) = 8。
對齊規則(其實很簡單優雅):
1.「內部對齊」:認為第乙個資料成員的offset為0,後續成員的offset必須對齊到它的型別的unit值的整數倍,比如char是隨便放到哪個位元組處都可以的(因為大小是1),而int則必須放到offset為4的整數倍處,以此解釋上面的struct A的部分記憶體布局為:
structAf
;};2.struct「向外」的對齊,1說的是struct內部的對齊規則,為什麼還要考慮「向外」呢?
假設我們定義了這樣乙個陣列:A data[5];
data[0]的offset為0,data[1]呢?目前為止,我們算出(未向外對齊的)sizeof(A) = 25,那麼data[1]的offset就是25了,data[2]的offset就是50了,這樣真的好嗎?
因為我們在1中假設第乙個成員的offset為0(其實剛好是任意型別的unit值的整數倍,因為x*0=0),但是25,50這些數字就不是了。
那麼該以誰為基準來對齊呢?就是以unit(struct Type)來對齊了,上述的struct A,unit(A) = 8,那麼25對齊到8的整數倍,就是32,所以sizeof(A) = 32,不信自己複製到機器上跑一遍~
綜上,其實struct的記憶體對齊規則很簡單。
拓展思考
1. 不過可以想想為什麼是以unit(struct Type)來對齊,而不是其資料成員中的任意一種型別的unit值呢?這其實得看清楚unit的具體意義:
struct裡出現過的所有內建型別的最大size!!!想想是不是^_^呢。
由最大的型別來對齊就可以保證即使struct物件排列成陣列也可以正確對齊了!
2. 編譯器有個預編譯指令:#pragam pack(x)巨集,它可以改變型別的unit值,具體如何自行google。
3 最後,延展開去,為什麼要做記憶體對齊?有什麼用?這個若有興趣,也可以去google一下。
關於題主的問題
裡面只有兩個資料成員:
int i;
union U u;
按照上面所說的規則,不過得先搞清楚union的大小,這個有點神奇,是最大的資料成員的size按照unit值最大的type對齊的結果,比如上面的union就是13往4的整數倍對齊,sizeof(U) = 16,而如果是下面的,則是sizeof(U) = 13。
union U ;
這都沒關係,繼續按上面說的規則做。
unit(U) = max(sizeof(char), sizeof(int)) = 4
unit(A) = max(sizeof(int), unit(U)) = 4
那麼有:
inti
;// 0-3
unionUu
;// 所以最終sizeof(A) = 20
END
2樓:胡金
題主不明白的估計不是單項大小怎麼算,而是哪些應該被計算吧。簡單點想就是類共用的資訊不會被儲存在例項物件裡,所以後面那些型別定義資訊不會被sizeof計算。
前面的就看對其了,還有一些編譯開關指令可以調整,願意的話以單位元組為對齊邊界都是可以的
3樓:少年遊
14年拿vs2010和gcc做的驗證,現在應該還沒有變吧。請大神指點!
如果沒改預設對齊的配置的話,如下面說列。
win下的位址是向min(最大基本型別,匯流排大小)對齊(32位4位元組,64位8位元組),成員向最大基本型別位元組對齊(包含類物件,也向類物件中最大基本型別大小對齊,陣列的總大小不算,陣列型別的大小算)。
其實位元組對齊就是位址對齊,要求成員的位址必須是能被min(基本型別,匯流排大小)整除的,最後類的填充要求下乙個位址可以被這個類的min(最大基本型別,匯流排大小)整除(為了相容陣列)。
rule1(位址規則):每個元素位址應該是min(資料匯流排長度,元素長度)的整數倍;64位OS資料匯流排為8,32位位址匯流排為4.;
rule2:每個元素相對結構體起始的偏移位址是其大小的整倍數;
rule3:每個結構體所佔大小應該是最大元素長度的整數倍;
rule4:每個結果體所佔大小應該是min(位址長度,元素長度)的整數倍;
linux有rule1,rule4;win有rule1-3
4樓:張小飛
c++的物件模型vs跟g++的實現在有虛函式的情況下有些地方
是不一樣的,標準裡邊沒有說怎麼實現,所以還是看你具體使用的編譯器實現,都說c++標準c++標準,可是很多地方都跟編譯器相關,你這個地方同理。都說32位系統,64位系統下int的位元組數不一樣了,相同的編譯器在不同的作業系統下肯定做處理了。所以這個題目未定義沒有標準答案
5樓:靈劍
跟編譯器實現有關係,int4個位元組,char[13]會對齊到4位元組是16,沒有虛表,正常應該是對齊到4位元組邊界是20,如果對齊到了8位元組邊界可能會是24
c語言為什麼輸入 乙個實數123 123輸出的結果會變?
林凱 簡單點說,十進位制數如何表示1 3呢,0.333333 再乘以幾個10也抹不掉小數點!二進位制數如何表示0.3呢?再乘以幾個2也抹不掉小數點!3.14159269不能用八位十進位制 表示 123.123同樣不能用二十三位的float表示 打比方和原理的分割線 浮點數由1位符號位 若干位指數字 ...
根據題目請講乙個故事?
kool aid ADC 我 我盾牆開了!傷害扛了!虛弱交了!大招給了!對面輔助和ADC加乙個打野都給我四層的被動暈住了!w也給你加雙抗了!你還打問號幹嘛!ADC 這就是是你a小龍害得我們倆個都給小龍噴死的理由? ADC 她的螢幕黑了侷促的睨我又飛快的看了看眼前的盲僧低下了頭對不起呀。我又死了 瞎子...
怎樣用c語言做到輸入乙個人的名字才會輸出乙個心
涇渭漳淮 我來寫個最最簡單的,一點廢話都沒有。int main return 0 xfan include intmain int 問題的意思是說,題主可以畫出乙個心,只是題主想問,怎樣輸入乙個名字再輸出這個心。只需要在程式最前面定義乙個字元陣列,再加if判斷判斷這個字元陣列如果 名字,就畫乙個心。...