(1)什麼是位元組對齊
乙個變數占用n
個位元組,則該變數的起始位址必須能夠被
n
整除,即
:
每個變數的起始存放位址
% n = 0
,
對於結構體,這個
n
取其成員種的資料型別佔空間的值最大的那個。
預設定義的指標,是cpu最大資料型別 如:對於32位cpu,char *p; 佔4個位元組
而定義了資料的儲存型別後,如:static char *p; 佔1個位元組
即:a1儲存位址addr1%a1對齊值=0,a2按順序後延,如果下乙個位址addr2%a2!=0就補空,後移儲存位址addr3。若addr3%a2!=0,繼續後移。
同時,每個記憶體塊為最大的對齊值n,不滿的要補空。
結構體中有結構體,把內中的結構體拆開看。
(2)為什麼要位元組對齊
記憶體空間是按照位元組來劃分的,從理論上說對記憶體空間的訪問可以從任何位址開始,但是在實際上不同架構的
cpu為了提高訪問記憶體的速度,就規定了對於某些型別的資料只能從特定的起始位置開始訪問。這樣就決定了各種資料型別只能按照相應的規則在記憶體空間中存放,而不能乙個接乙個的順序排列。
舉個例子,比如有些平台訪問記憶體位址都從偶數字址開始,對於乙個
int型(假設
32位系統
),如果從偶數字址開始的地方存放,這樣乙個讀週期就可以讀出這個
int資料,但是如果從奇數字址開始的位址存放,就需要兩個讀週期,並對兩次讀出的結果的高低位元組進行拼湊才能得到這個
int資料,這樣明顯降低了讀取的效率。
(3)如何進行位元組對齊
每個成員按其型別的對齊引數
(通常是這個型別的大小
)和指定對齊引數
(不指定則取預設值
)中較小的乙個對齊,並且結構的長度必須為所用過的所有對齊引數的整數倍
,不夠就補空位元組。
這個規則有點苦澀,可以把這個規則分解一下,前半句的意思先獲得對齊值後與指定對齊值進行比較
,其中對齊值獲得方式如下:
1. 資料型別的自身對齊值為:對於
char
型資料,其自身對齊值為
1,對於
short型為2
,對於int, long, float
型別,其自身對齊值為
4,對於
double
型別其自身對齊值為
8,單位為位元組。 2.
結構體自身對齊值:其成員中自身對齊值最大的那個值。
其中指定對齊值獲得方式如下:
#pragma pack (value)
時的指定對齊值
value。
未指定則取預設值。
後半句的意思是主要是針對於結構體的長度而言,
對於結構體,它可能使用了多種資料型別,那麼這句話翻譯成對齊規則: 每個成員的起始位址
% 自身對齊值
= 0,如果不等於
0 則位址後移直到符合規則,前面的補空達到對齊值。
換句話說,對於結構體而言,結構體在在記憶體的存放順序用如下規則即可對映出來: (
一)單獨的
每個成員的起始位址
% 每個成員的自身對齊值
= 0,如果不等於
0 就後移,前面補空使得每個成員記憶體塊為結構體中最大的對齊值。 (
二)結構體的長度必須為結構體的自身對齊值的整數倍
,不夠就補空位元組。
舉例:typedef struct
a;sizeof(a) 結果為: 12 記憶體位置為: $*$$ $*** $$$$ 注意:每個成員首位址必須為自身對齊值的整數倍。
typedef struct
b;sizeof(b)結果為:16 記憶體位置為:$$$$ $$** $$$$ $*$$
typedef struct
c;sizeof(c)結果為:28 記憶體位置為:$$$$ $*$$ $*$$ $*** $$$$ $*$$ $$$$
c語言中結構體對齊詳解
為什麼要對齊?現代計算機中記憶體空間都是按照byte劃分的,從理論上講似乎對任何型別的變數的訪問可以從任何位址開始,但實際情況是在訪問特定型別變數的時候經常在特 定的記憶體位址訪問,這就需要各種型別資料按照一定的規則在空間上排列,而不是順序的乙個接乙個的排放,這就是對齊。對齊的作用和原因 各個硬體平...
關於C語言中的結構體對齊
關於c語言中的結構體對齊 1 什麼是位元組對齊 乙個變數占用 n 個位元組,則該變數的起始位址必須能夠被 n 整除,即 存放起始位址 n 0,對於結構體而言,這個 n 取其成員種的資料型別佔空間的值最大的那個。2 為什麼要位元組對齊 記憶體空間是按照位元組來劃分的,從理論上說對記憶體空間的訪問可以從...
C語言結構體儲存及對齊
規則1 結構體的資料成員中,第乙個成員的offset為0 規則2 結構體的資料成員中,每個成員的offset為本成員大小的整數倍 規則3 若結構體a作為另乙個結構體b的資料成員,則結構體a作為乙個整體參與規則1和規則2 規則4 結構體的總大小 sizeof 不是簡單的所有成員大小的總和,為該結構體內...