linux下位元組對齊

2021-06-18 01:45:33 字數 3862 閱讀 9342

一,記憶體位址對齊的概念

計算機記憶體中排列、訪問資料的一種方式,包含基本資料對齊和結構體資料對齊。

32位系統中,資料匯流排寬度為32,每次能夠讀取4位元組資料。位址匯流排為32,最大定址空間為4gb。但是由於最低位a[0]~a[1]是不用於定址的,因此只能訪問4的倍數的位址空間,但是定址空間還是2^30*字長=4gb。

因此記憶體中除了結構體中成員變數之外的基本型別的開始的首位址最低兩位都是0。基本型別資料對齊就是資料在記憶體中的偏移位址必須是乙個字的倍數,以提高讀取資料時的效能。為了對齊資料,必須在上個資料結束和下個資料開始處插入一些位元組,這就是結構體資料對齊。

二,不進行對齊的影響

例如int a的位址是0x00fffff3,則其位元組分布在0x00fffff3~0x00fffff6空間內,為了讀取這個int,cpu必須對 0x00fffff0和0x00fffff4進行兩次記憶體讀取,並處理得出的中間結果。兩次記憶體訪問將會浪費大量的時間,因為記憶體訪問的速度遠小於cpu 處理指令的速度。

三,結構體的記憶體位址對齊

結構體本身必須是4位元組對齊的,而其成員變數則處理規則如下。

以下是microsoft和gnu對x86架構32位系統的結構體成員的預設對齊方式:

char  1位元組對齊

short  2位元組對齊

int      4位元組對齊

float  4位元組對齊

double windows是8位元組對齊,linux是4位元組對齊

當某乙個成員後邊的成員變數要求的位址對齊較大,則應該填入一些位元組。且總的結構體大小為最大對齊的倍數,因此最後可能還要填充一些字元。

因為上述結構體對齊的原因,將結構體成員按照大小遞增/遞減方式排序,可以減少結構體占用的空間大小。而這樣同時使得對整個結構體的訪問的效率變高了(占用小,整個的訪問次數可以降低)。

另外乙個提高效率的方法是把一些占用位元組數較少的成員合併到位元組數占用大的成員,形成union型別。

四。準則

其實位元組對齊的細節和具體編譯器實現相關,但一般而言,滿足三個準則:

1. 結構體變數的首位址能夠被其最寬基本型別成員的大小所整除;

2. 結構體每個成員相對於結構體首位址的偏移量都是成員大小的整數倍,如有需要編譯器會在成員之間加上填充位元組;

3. 結構體的總大小為結構體最寬基本型別成員大小的整數倍,如有需要編譯器會在最末乙個成員之後加上填充位元組。

五.基本概念

位元組對齊:計算機儲存系統中以byte為單位儲存資料,不同資料型別所佔的空間不同,如:整型(int)資料佔4個位元組,字元型(char)資料佔乙個位元組,短整型(short)資料佔兩個位元組,等等。計算機為了快速的讀寫資料,預設情況下將資料存放在某個位址的起始位置,如:整型資料(int)預設儲存在位址能被4整除的起始位置,字元型資料(char)可以存放在任何位址位置(被1整除),短整型(short)資料儲存在位址能被2整除的起始位置。這就是預設位元組對齊方式。

六、結構體長度求法

1.成員都相同時(或含陣列且陣列資料型別同結構體其他成員資料型別): 

結構體長度=成員資料型別長度×成員個數(各成員長度之和); 

結構體中陣列長度=陣列資料型別長度×陣列元素個數;

2.成員不同且不含其它結構體時; 

(1).分析各個成員長度; 

(2).找出最大長度的成員長度m(結構體的長度一定是該成員的整數倍); 

(3).並按最大成員長度出現的位置將結構體分為若干部分; 

(4).各個部分長度一次相加,求出大於該和的最小m的整數倍即為該部分長度 

(5).將各個部分長度相加之和即為結構體長度

3.含有其他結構體時: 

(1).分析各個成員長度; 

(2).對是結構體的成員,其長度按b來分析,且不會隨著位置的變化而變化; 

(3).分析各個成員的長度(成員為結構體的分析其成員長度),求出最大值; 

(4).若長度最大成員在為結構體的成員中,則按結構體成員為分界點分界; 

其他成員中有最大長度的成員,則該成員為分界點; 

求出各段長度,求出大於該和的最小m的整數倍即為該部分長度 

(5).將各個部分長度相加之和即為結構體長度

七、空結構體 struct s5 ; sizeof( s5 ); // 結果為1

「空結構體」(不含資料成員)的大小不為0,而是1。試想乙個「不佔空間」的變數如何被取位址、兩個不同的「空結構體」變數又如何得以區分呢於是,「空結構體」變數也得被儲存,這樣編譯器也就只能為其分配乙個位元組的空間用於佔位了。

八、有static的結構體 struct s4;

c語言結構體中不能有static變數,++可以,

c中struct只是型別宣告,沒有記憶體空間的分配,而static變數是需要分配記憶體的。

靜態變數存放在全域性資料區內,而sizeo

f計算棧中分配的空間的大小

,故不計算在內,s4的大小為4+4=8。

#pragma pack(n)指令設定1.2.4對齊。linux下最高位4.#pragma pack()指令預設為四。

九.union

union的長度取決於其中的長度最大的那個成員變數的長度。即union中成員變數是重疊擺放的,其開始位址相同。

其實union(共用體)的各個成員是以同乙個位址開始存放的,每乙個時刻只可以儲存乙個成員,這樣就要求它在分配記憶體單元時候要滿足兩點:   

1.一般而言,共用體型別實際占用儲存空間為其最長的成員所佔的儲存空間;   

2.若是該最長的儲存空間對其他成員的元型別(如果是陣列,取其型別的資料長度,例int   a[5]為4)不滿足整除關係,該最大空間自動延伸;   

我們來看看這段**:

union mm;

本來mm的空間應該是sizeof(int)*5=20;但是如果只是20個單元的話,那可以存幾個double型(8位)呢?兩個半?當然不可以,所以mm的空間延伸為既要大於20,又要滿足其他成員所需空間的整數倍,即24 

所以union的儲存空間先看它的成員中哪個佔的空間最大,拿他與其他成員的元長度比較,如果可以整除就行。

Linux 位元組序與位元組對齊優化

1.位元組序跟linux windows無關,是由cpu構架決定 同乙個cpu不管裝的是windows 或 linux 位元組序都是一樣的 2.位元組對齊 linux 全用 attribute packed 作用於結構體,類似於pragma packet 1 使用方法如下 typdef struct...

結構體位元組對齊 windows下

結構體位元組對齊 在用sizeof運算子求算某結構體所佔空間時,並不是簡單地將結構體中所有元素各自佔的空間相加,這裡涉及到記憶體位元組對齊的問題。從理論上講,對於任何 變數的訪問都可以從任何位址開始訪問,但是事實上不是如此,實際上訪問特定型別的變數只能在特定的位址訪問,這就需要各個變數在空間上按一定...

位元組順序 位元組對齊

一.位元組順序的產生 在計算機中,資料是以位元組為單位存放的,而c語言中只有char才是乙個位元組,其他如int,float都是大於乙個位元組,所以就存在將資料按怎樣的順序存放的問題。一般有大端序和小端序兩種方式,特殊的還有混合序,也就是兩種存放方式同時存在於乙個計算機系統中。上面講的都是主機位元組...