一.記憶體對齊
1.什麼是記憶體對齊
假設我們同時宣告兩個變數:
char a;
short b;
如果a的位址是0x0000,那麼b的位址將會是0x0002或者是0x0004。
因為cpu每次都是從以2位元組(16位cpu)或是4位元組(32位cpu)的整數倍的記憶體位址中讀進資料的。
如果變數b的位址是0x0001的話,那麼cpu就需要先從0x0000中讀取乙個short,取它的高8位放入b的低8位,
然後再從0x0002中讀取下乙個short,取它的低8位放入b的高8位中,這樣的話,為了獲得b的值,cpu需要進行了兩次讀操作。
但是如果b的位址為0x0002,
那麼cpu只需一次讀操作就可以獲得b的值了。所以編譯器為了優化**,往往會根據變數的大小,將其指定到合適的位置,即稱為記憶體對齊
(對變數b做記憶體對齊,a、b之間的記憶體被浪費,a並未多佔記憶體)。
2.結構體內存對齊規則(請記住三條記憶體規則(在沒有#pragam pack巨集的情況下)
結構體所占用的記憶體與其成員在結構體中的宣告順序有關,其成員的記憶體對齊規則如下:
(1)每個成員分別按自己的對齊位元組數和ppb(指定的對齊位元組數,32位機預設為4)兩個位元組數最小的那個對齊,這樣可以最小化長度。如在32bit的機器上,int的大小為4,因此int儲存的位置都是4的整數倍的位置開始儲存。
(2)複雜型別(如結構)的預設對齊方式是它最長的成員的對齊方式,這樣在成員是複雜型別時,結構體陣列的時候,可以最小化長度。
(3)結構體對齊後的長度必須是成員中最大的對齊引數(ppb)的整數倍,這樣在處理陣列時可以保證每一項都邊界對齊。
(4)結構體作為資料成員的對齊規則:在乙個struct中包含另乙個struct,內部struct應該以它的最大資料成員大小的整數倍開始儲存。
如 struct a 中包含 struct b, struct b 中包含資料成員 char, int, double,則 struct b 應該以sizeof(double)=8的整數倍為起始位址。
3.例項演示:
struct a
; // 記憶體大小:sizeof(a) = (1+7) + 8 + (4+4) = 24, 補齊[20]...[23] ---- 規則3
struct b
; // 記憶體大小:sizeof(b) = (4+4) + 24 + (1+7) = 40, 補齊[33]...[39]
*注釋:(1+7)表示該資料成員大小為1,補齊7位;(4+4)同理。
4.32位編譯器:32位系統下指標占用4位元組
char :1個位元組
char*(即指標變數): 4個位元組(32位的定址空間是2^32, 即32個bit,也就是4個位元組。同理64位編譯器)
short int : 2個位元組
int: 4個位元組
unsigned int : 4個位元組
float: 4個位元組
double: 8個位元組
long: 4個位元組
long long: 8個位元組
unsigned long: 4個位元組
64位編譯器:64位系統下指標占用8位元組
char :1個位元組
char*(即指標變數): 8個位元組
short int : 2個位元組
int: 4個位元組
unsigned int : 4個位元組
float: 4個位元組
double: 8個位元組
long: 8個位元組
long long: 8個位元組
unsigned long: 8個位元組
編譯之 記憶體對齊
現代計算機中記憶體空間都是按照 byte 劃分的,也就是位元組,從理論上講似乎對任何型別的變數的訪問可以從任何位址開始,但實際情況是在訪問特定型別變數的時候經常在特定的記憶體位址訪問,這就需要各種型別資料按照一定的規則在空間上排列,而不是順序的乙個接乙個的排放,這就是對齊 從cpu的角度來說,cpu...
記憶體對齊及大小端
一 記憶體對齊問題 先看乙個面試題 c union s struct b long a union s 求sizeof union s 24 sizeof struct b 32 有幾個問題需要回答,記憶體對齊的規則是什麼?這個union 物件在記憶體中資料是怎麼排列的?大端小端都一樣嗎?1 記憶體...
記憶體對齊及 pragma pack的使用
在預設情況下,c編譯器為每乙個變數或是資料單元按其自然對界條件分配空間。在結構中,編譯器為結構的每個成員按其自然對界 alignment 條件分配空間。各個成員按照它們被宣告的順序在記憶體中順序儲存 成員之間可能有插入的空位元組 第乙個成員的位址和整個結構的位址相同。c編譯器預設的結構成員自然對界條...