一、位元組對齊的定義
計算機在訪問特定型別變數的時候經常在特定的記憶體位址訪問,這就需要各種型別資料按照一定的規則在空間上排列,而不是順序的乙個接乙個的排放,這就是對齊。
二、對齊的作用和原因
1、平台原因(移植原因):不是所有的硬體平台都能訪問任意位址上的任意資料的;某些硬體平台只能在某些位址處取某些特定型別的資料,否則丟擲硬體異常。各個硬體平台對儲存空間的處理上有很大的不同。一些平台對某些特定型別的資料只能從某些特定位址開始訪問。比如有些架構的cpu在訪問乙個沒有進行對齊的變數的時候會發生錯誤,那麼在這種架構下程式設計必須保證位元組對齊。
2、效能原因:最常見的是如果不按照適合其平台要求對資料存放進行對齊,會在訪問效率上帶來損失。資料結構(尤其是棧)應該盡可能地在自然邊界上對齊。原因在於,為了訪問未對齊的記憶體,處理器需要作兩次記憶體訪問,而對齊的記憶體訪問僅需要一次訪問。比如有些平台每次讀都是從偶位址開始,如果乙個int型(假設為32位系統)如果存放在偶位址開始的地方,那麼乙個讀週期就可以讀出這32bit,而如果存放在奇位址開始的地方,就需要2個讀週期,並對兩次讀出的結果的高低位元組進行拼湊才能得到該32bit資料。顯然在讀取效率上下降很多。
三、位元組對齊的規則
每個特定平台上的編譯器都有自己的預設「對齊係數」(也叫對齊模數),一般來講,在32位機器上,預設對齊數是4位元組, 64位機器上預設對齊數是8位元組. 我們可以通過預編譯命令#pragma pack(n),n=1,2,4,8,16 來改變這一係數,其中的n就是你要指定的「對齊係數」。
注意,以下例子在64位os下
規則一、 結構體中每個資料成員在結構體中的起始位置,應該是 min(這個資料成員的位元組數, 對齊係數)。比如,下面的兩個例子:
例一:
struct exmp
;
在例一中,cha a佔乙個位元組,起始位置從0開始, int c 佔4個位元組,但它的起始位置不能從1,開始,而是從4開始,double b 佔8個位元組,從位置8開始,這三個資料成員共占用4+4+8=16個位元組
例二:
struct exmp
;//sizeof (struct exmp) = 8 + 8 + 4 + 4 = 24
在例二中, char a 占用乙個位元組,位置從0開始,double b佔8個位元組位置從8開始,位置1~7填充佔位符,int c 從 16開始,佔4位元組,這裡要注意,在確定完,各個資料成員的起始位置和所佔位元組後,整個結構體的大小,還應該做一些調整,以遵守如下規則:
規則二、整個結構體的大小,應該是min(其最長資料成員所佔位元組, 對齊係數)的整數倍。 例二中,三個資料成員所佔的位元組是8 + 8 + 4 = 20, 20並不是最長資料成員(double b)所佔位元組數(8 byte)的整數倍,所以末尾再加四位元組湊成24。
例三:
#pragma pack(2)
struct exmp
;// sizeof(struct exmp) = 2 + 8 + 4 = 14
在例三中,指定了對齊係數是2, char a佔乙個位元組,仍然從0開始,double 佔8個位元組,但起始位置從min (8,2)= 2位置開始,int c佔4位元組,起始位置從min(4,2)= 2的整數倍位置10開始,size = 2+8+4 = 14,在這種情況下,整個結構體的大小需要是(對齊係數=2,最大資料成員所佔位元組double b=8)= 2的整數倍
規則三:如果有巢狀結構體,那麼內嵌結構體的第乙個成員變數在外結構體中的偏移量,是「min(對齊位元組,內嵌結構體中那個資料型別大小最大的成員變數)」的倍數。
例四:
struct test
ch; char ci;
};// sizeof(struct test) = 40
例四中,int a 佔4位元組,char b,c佔一位元組,後面填充兩個位元組,int d起始位置8,佔四個位元組,char e,佔乙個位元組,起始位置12, 結構體 child 中的乙個資料成員的起始位置=min(最長資料成員所佔位元組 long long g =8, 對齊係數=8)= 8的整數倍,所以 char e 後填充3位元組,int f從16開始,f後填充4位元組,long long f 從24開始,char ci,占用1位元組,填充7位元組
總結:位元組對齊,就是要解決兩件事兒:
1. 當前資料成員從哪個偏移位置開始,這個起始位置取決於min(這個資料成員的位元組數, 對齊係數)
2. 當前資料成員後需要填充多少位元組,取決於下乙個資料成員的起始位置。當 當前資料成員為結構體中最後乙個資料成員時,則填充位元組數取決於規則二
C 中位元組對齊以及位元組對齊的意義
對下面的類 class b 類b 物件的大小,如果直接計算是18 4 2 8 4 但是 sizeof b 結果是24。多出來的 6個位元組是怎麼回事呢?其實是記憶體對齊的原因。編譯器在預設的情況下,分配給各個成員變數的記憶體大小似乎是向佔最大空間的成員變數對齊的 這裡我不敢肯定,還沒看到權威的說法 ...
C 中的位元組對齊
本部落格 位元組對齊 1.基本概念 位元組對齊 計算機儲存系統中以byte為單位儲存資料,不同資料型別所佔的空間不同,如 整型 int 資料佔4個位元組,字元型 char 資料佔乙個位元組,短整型 short 資料佔兩個位元組,等等。計算機為了高速的讀寫資料,預設情況下將資料存放在某個位址的起始位置...
C 類中的位元組對齊
結果輸出如下 出人意料的,這兩行語句 cout sizeof p endl cout sizeof p.x sizeof p.y sizeof p.z endl 的輸出內容為 129 4 4 1 12 這是什麼原因?解釋這種原因的答案是 位元組對齊 乙個c 的類的物件或結構體中含有若干成員,其佔占用...