c++对象长度之内存对齐(2)
文章目錄
- 內存對齊
- 例題a
- 例題b
- 例題c
內存對齊
在VC++6.0中,類和結構體中的數據成員是根據它們在類或結構體中出現的順序來依次申請申請內存空間的,由于內存對齊的原因,它們并不一定會像數組那樣連續地排列。由于數據類型的不同,因此占用的內存空間大小也會不同,因此占用的內存空間大小也會不同,在申請內存時,會遵守一定的規則。
要找對齊的話,我個人感覺應該先找到
編譯器的指定對齊值,因為結構體中的當前數據成員類型長度為M,指定的對齊值是N,那么實際的對齊值為q=min(M,N),其成員的地址安排在q的倍數上。
但是,并非設定了默認對齊值就將結構體的對齊值鎖定。如果結構體中的數據成員類型最大值為M,指定的對齊值是N,那么實際對齊值為q=min(M,N)
三準則如下:
a.數據成員對其規則:結構(或聯合)的數據成員,第一個數據成員放在offset為0的地方,以后每個數據成員存儲的子成員大小(只要該成員有子成員,比如說是數組,結構體等)的整數倍開始(比如int 在32位機為4字節則要從4的整數倍地址開始存儲)
b.結構體作為成員:如果一個結構里有某些結構體成員,則結構體成員要從其內部最大元素的整數倍地址開始存儲.(struct a里存有 struct b,b里有 char ,int ,double 等元素,那b應該從8的整數倍開始存儲.)
c.收尾工作:結構體的總大小,也就是sizeof的結果,必須是其內部最大成員的整數倍,不足的要補齊
來舉一個最簡單的例子吧,請看截圖
例題a
這個int 類型數據占據四個存儲單元是 0~ 3(四個字節),但由于double 是8個字節,根據準則a,那么我們需要填充四個字節,從存儲單元8開始填double b,即存儲單元8~15是b的數據,所以存儲單元0 ~15是16個字節
例題b
此例題說明 準則二 和準則三的作用
在對象bq中,有 int a,double aa,char c,根據三準則中準則一,首先int a占 4字節(存儲單元0 ~ 3);然后根據準則二 double aa 排列的存儲單元是 8 ~ 15,char c排列的存儲單元是 16;根據準則三收尾功能填充,則對象bq占了24字節(最后0 ~ 23占了24個字節);
然后da對象中,有 char aa ,b a,int aaa,根據三準則中準則一,首先char aa 占一字節(存儲單元0);然后 根據準則二b a排列的存儲單元是 8 ~ 31,int aaa排列的存儲單元是32~35;根據準則三收尾功能,填充36 ~39(最后0 ~ 39占了40個字節);
提示:當結構體中以數組作為成員時,將根據數組元素的長度計算對齊值,而不是按數組的整體大小去計算,例題如下:
例題c
解釋:
在對象bq中,有double a[2],int aa,char c,根據三準則中準則一,首先double a[2]占 16字節(存儲單元0 ~ 15);然后根據準則一 int aa 排列的存儲單元是 16 ~ 19,char c排列的存儲單元是 20;根據準則三收尾功能填充,在這里我們需要討論了,如果用double 數組總長度來帶入準則三的話,那么應該為32,所以此排除;如果用double單個元素的長度來帶入準則三的話,那么符合
當然在這里還有同學肯定有疑問,如果我以 int aa 帶入準則三呢?(因為數組這種東西比較特殊,跟其它的有點不一樣,萬一特殊呢?對吧?)
所以的話,我已經準備好下面的東西來解釋了
哎呀,把int aa改成了char aa,還是24呀,那么是不是就驗證了我的說法呢?
好啦,這里告一段落,給大家來個題目,下面會輸出什么呢?
class b {double a; char c; }; void main() {b bq;int lengthbq = sizeof(bq); cout << lengthbq #pragma pack(N)用法如下所示:
VC++6.0 中可使用預編譯指令#pragma pack(N)來調整對齊大小,當上面把對齊值改過后,它并非原來的16字節,而是變成9字節。
使用pack修改對齊值也并非一定會生效,與默認對齊值一樣,對需要參考結構體中數據成員類型。當設定的對齊值大于結構體中的數據成員類型大小時,此對齊值是無效的。對齊值的計算流程換種說法是:將設定的對齊值與結構體中最大的基本類型數據成員的長度進行比較,取兩者之間的較小值。
如下
驗證以上說法
總結
以上是生活随笔為你收集整理的c++对象长度之内存对齐(2)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2020-11-27(switch的优化
- 下一篇: 详解虚函数的实现过程之初探虚表(1)