C 位元組對齊問題

2021-06-10 09:35:52 字數 2643 閱讀 9674

關於c++位元組對齊問題

關於c/c++的位元組對齊

這兩天寫解析swf檔案的程式,在結構體指標和從檔案中讀出來的進行轉換的時候遇到一些問題,就是有乙個struct a,例如:

struct a

char flag;

int length;

int id; 

然後乙個飄逸的 struct a *a = (struct a*)buffer;   // 世界一下清靜咯

c++的位元組對齊。看到下面這篇文章說的挺清晰的,就轉了過來。

關於c/c++的位元組對齊

最近研究c++的資料型別和資料大小時發現,位元組對齊實際上是乙個c/c++程式設計師無法忽視的乙個問題.所以進行了初步的研究.

1.為什麼會出現記憶體對齊問題-從x86 cpu架構說起

相信絕大多數計算機系和軟體學院的學生都學過計算機組成原理這門基礎課程,所以不作入門引導了,沒有相關背景的可以補補相關課程資料.常有人問我,既然是按位元組定址方式,為何會出現位元組對齊問題呢?難道是記憶體不是連續的嗎?

這個問題實際上和cpu與記憶體的連線方式有關,我們知道cpu會通過位址匯流排address bus與cpu連線用於定址,用data bus資料匯流排連線用於獲取資料,而記憶體通常是ram構成的複雜陣列。

對於這個ram陣列(實際記憶體可能更複雜,但是原理類似), 前16個記憶體位址排列對應記憶體單元關係如下:

對照上圖,是不是發現,對於每個記憶體操作週期,每個位址實際上可以讀取4個bytes的資料呢,那麼假設你有乙個int型的資料儲存在位址1或者2或者 3,那麼,是不是乙個cpu記憶體時鐘週期不夠取出這個資料呢?這樣是不是效率會很低下?這也就是為什麼我們需要記憶體對齊了,雖然現代cpu和編譯器已經對 此做了很多優化,但是c/c++由於特殊性,程式設計師必須了解這個細節.

2.c/c++記憶體對齊的方式

c/c++中的結構/類的成員變數在對齊在記憶體中的排列是與它們擺放的先後順序相關的,先看看下面的結構

1 struct malign_a

2 ;

這個結構的sizeof(malign_a)是多少呢?1+2+1+4 =8?嗎?這個實際上不對,那麼,如何對齊的呢?

由於char是1個byte,所以不管他在什麼位置,都可以用乙個記憶體週期讀出資料,short是半個字也就是2 bytes,這個時候假如它的位址是某個邊界位置上,那麼,也需要兩個記憶體週期來讀取,以此類推.所以,記憶體對齊就是加入填充padding無意義的資料 來保證某個資料位於乙個可以通過最少記憶體週期的位置,比如double型只有位址位於%4等於0的位置,才能保證2個週期讀出.

同時對於每個具體平台,不同的編譯器有不同的指定的對齊模式,比如c/c++可以通過

1 #pragma pack(n) //n為1,2,4,8,16等

來指定對齊.當然,一般x86 32位機器下,都是預設4位元組對齊的.這個n也稱為對齊模數.

對齊策略如下:

1.結構體成員對齊:按某成員資料本身大小以及指定大小中較小者對齊

2.結構體整體對齊:按所有成員中最大者和對齊模數中較小者對齊

所以上述結構體按預設對齊方式如下:

1.a是char型別,可以在任意位置,位於位置0

2.b是short型別,2比預設的4小,所以按2位元組對齊,所以在a後面填充1個位元組,b必須位於位置2,佔兩個位元組

3.c是char型別,位於位置4

4.d是int型別,4<=4,所以按4位元組對齊,需要在c後面填充3個位元組,位置為8

5.由於最大成員是4,預設是4,所以結構已經按4對齊,所以總位元組數為12

再把原來的結構體成員位置改動一下:

1 struct malign_b

2 ;

這個結構的大小為8,對齊過程如下:

1.a是char型別,可以在任意位置,位於位置0

2.c是char型別,位於位置1

3.b是short型別,2比預設的4小,所以按2位元組對齊,這時候恰好位於位置2

4.d是int型別,4 5.由於最大成員是4,預設是4,所以結構已經按4對齊,所以總位元組數為8

最後為了加深理解,我們來看看下面這個結構按對齊模數2對齊時候的memory layout

01 #pragma pack(push)

02 #pragma pack(2)

03 struct malign_b

04 ;

10 #pragma pack(pop)

它的大小為10,當指定為對齊模數2時候

1.由於a是char,1<2,位於位置0

2.由於d是int,4>2,所以按2位元組對齊,所以必須在a後面填充乙個位元組,位於位置2,

3.c是char,位置為6

4.b是short,所以必須在c後面填充乙個位元組,位置為8

5.最大的是4,所以按2對齊,上述結果其實已經整體是按2對齊,所以總數為10

C 位元組對齊問題

關於c 位元組對齊問題 關於c c 的位元組對齊 這兩天寫解析swf檔案的程式,在結構體指標和從檔案裡讀出來的進行轉換的時候遇到一些問題,就是有乙個struct a,比如 struct a char flag int length int id 然後乙個飄逸的 struct a a struct a...

C中位元組對齊問題

好多筆試中,會考結構體的sizeof是多少,這就涉及到了位元組對齊問題。vc或gcc編譯器,預設按4位元組對齊 什麼叫位元組對齊?就是資料在記憶體中存放的方式,它存放的位址需要是它長度的整數倍。比如單位元組放在什麼位址都可以,雙位元組資料只能存放在偶位址上,4位元組數只能存放在是4的倍數的位址上。注...

位元組對齊問題

現代計算機中記憶體空間都是按照byte劃分的,從理論上講似乎對任何型別的變數的訪問可以從任何位址開始,但實際情況是在訪問特定型別變數的時候經常在特 定的記憶體位址訪問,這就需要各種型別資料按照一定的規則在空間上排列,而不是順序的乙個接乙個的排放,這就是對齊。對齊的作用和原因 各個硬體平台對儲存空間的...