C++ 结构体内存对齐
剛出學校那會,出去找實習工作,面試答題被問到結構體內存大小的問題,雖然自己以前接觸過,但是也還是答錯了,最終面試的這份工作黃了。一年后的最近,還是在找工作的路上,面試了一家游戲公司,其中也是答題環節有一道題被問到結構體的內存大小,也還是答錯了,最后面試也還是黃了。
到了現在自己才醒悟過來,這些知識點是有多么的重要,所以咬緊牙,把這個內容的知識點啃下來,寫下這篇博客記錄下來!
先看一段簡單的程序
#include <iostream>using namespace std;typedef struct A {char c;int i; };typedef struct B {char c;int i;double d; };typedef struct C {char c;int i;double d;char c1; };int main(void) {cout << "struct A size = " << sizeof(struct A) << endl;cout << "struct B size = " << sizeof(struct B) << endl;cout << "struct C size = " << sizeof(struct C) << endl;return 0; }如果不運行,那么大家知道結構體A、B、C所占用的內存大小是多少嗎?
運行截圖:
以上輸出的結果并非實際成員占用的字節數,這就是結構體的內存對齊!
按照我們正常的邏輯,結構體A的內存大小應該是5個字節,結構體B的內存大小應該是13個字節,結構體C的內存大小應該是14字節才對!
但是為什么是8、16和24呢?將在下面進行講解。
結構體內存對齊原因
平臺原因(移植原因):
“不是所有的硬件平臺都能訪問任意地址上的任意數據;某些硬件平臺只能在某些特定地址處取某些特定的數據,否則就會拋出硬件異常”。也就是說在計算機在內存讀取數據時,只能在規定的地址處讀數據,而不是內存中任意地址都是可以讀取的。
效率原因:
正是由于只能在特定的地址處讀取數據,所以在訪問一些數據時,對于訪問未對齊的內存,處理器需要進行兩次訪問;而對于對齊的內存,只需要訪問一次就可以。 其實這是一種以空間換時間的做法,但這種做法是值得的。
結構體對齊規則
第一個成員在結構體變量偏移量為0 的地址處,也就是第一個成員必須從頭開始。
其他成員變量要對齊到某個數字(對齊數)的整數倍的地址處。對齊數為編譯器默認的一個 對齊數與該成員大小中的較小值。vs中默認值是8 Linux默認值為4(可以通過#pragma pack (N) 修改,使用#pragma pack(show) 可以查看對齊值),但修改時N的取 值只能設置成1, 2,4,8,16.
結構體總大小為最大對齊數的整數倍。(每個成員變量都有自己的對齊數)
如果嵌套結構體,嵌套的結構體對齊到自己的最大對齊數的整數倍處,結構體的整體大小就是 所有最大對齊數(包含嵌套結構體的對齊數)的整數倍。(具體詳情,請看下面代碼結構體G)
結構體對齊的規則都是依據上面四條規則進行的!
結構體對齊示例
typedef struct A {char c;int i; };根據第二和第三條規則,VS中最大默認對齊數是8,結構體中最小的是int類型的4,8 < 4,所以結構體A的對齊數是4.
所以即使char類型占一個字節,但是他在內存中也會占用4個字節,來對齊4字節數,這就是所謂的,犧牲空間來換取時間!
后面的也是一樣的道理!
如果是這樣的結構體,那么他們的內存將會是多少呢?
typedef struct D {char c;int i;double d;char c1;int b;char c2; };typedef struct E {int i;double d;char c;double d2; };typedef struct F {int i;double d;char c;double d2;int i2;int i3;char c2;char c3;char c4;int i4; };typedef struct G {int i;double d;struct E e;char c;double d2; };
下面是他們的內存關系圖:
上述四張圖基本涵蓋了所有情況,希望這四張圖大家能看明白是怎么個回事!
我本人的理解:
以它為例,
首先我會先找到結構體中最大的變量字節大小(內部結構體除外),然后使用加法原則向其對齊。(結構體D的對齊數是8)
c 是1個字節,i是4個字節,c + i 等于5字節,為了符合內存對齊的原則,他倆占用最前方8個字節的內存,當然c是占4個字節,i也是占4個字節,這樣4 + 4 等于8,才符合內存對齊。
d是8個字節,緊接著后面存儲8個字節。
c1是一個字節,b是4個字節,計算規格和上面一樣,占用8個字節。
最后剩余一個c2是一個字節,當然為了符合內存對齊的原則他在結構體中是占8個字節的。
所以最后計算出內存大小為:
(c + i) == 8(字節)
d == 8(字節)
(c1 + b) == 8(字節)
c2 == 8(字節)
8 + 8 + 8 + 8 == 32(字節)
相信再配合下圖,一定可以理解是什么原理的:
總結
結構體內存對齊這是比較底層的知識點了,當然這也是我們程序員需要掌握的,特別是服務器開發人員。
對齊時需要注意對齊數!
總結
以上是生活随笔為你收集整理的C++ 结构体内存对齐的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 需要换个环境
- 下一篇: Android系统驱动【转】