好多筆試中,會考結構體的sizeof是多少,這就涉及到了位元組對齊問題。(vc或gcc編譯器,預設按4位元組對齊)
什麼叫位元組對齊?
就是資料在記憶體中存放的方式,它存放的位址需要是它長度的整數倍。比如單位元組放在什麼位址都可以,雙位元組資料只能存放在偶位址上,4位元組數只能存放在是4的倍數的位址上。
注意:它與cpu訪問的方式無關,32位機器就是按照4位元組來訪問的,因為它的資料匯流排是32位,不會以資料在記憶體中的對齊方式而變化。
一、對於標準資料型別,它的位址是他長度的整數倍就行了。
char:1位元組對齊(有符號無符號一樣)
short:2
int:4
long:4
float:4
double:8
二、對於非標準型別,對齊方式如下:
1、陣列:按照基本資料型別對齊,只要第乙個資料對齊了,後面的自然就對齊了。
2、聯合體:按照元素中最大的長度對齊。
3、結構體:結構中每個資料都要對齊。
其中,因為結構體對齊最複雜,所以也最常見。
下面舉幾個結構體例子:
1、struct st1 ;
它佔幾個位元組呢?正確答案是:20
分析如下:char本來佔1個位元組,因為4位元組對齊,所以需要在x1後空出3個位元組,接下來才是x2.x3本來佔10個位元組,但由於最後兩個位元組後面也需要空出2個位元組,所以x3佔12個位元組。這樣4+4+12=20個位元組。
2、如下兩個類似的結構體,成員相同,只是順序不同,則所佔位元組不同。
struct a ;
struct b ;
正確答案:a佔12個位元組,b佔8個位元組。
分析:a:a(1個位元組)之後是b(4個位元組),需要在a之後空著3個位元組。4+4+4=12.
b:b先佔4個位元組,緊接著a佔1個位元組,然後c佔2個位元組,那麼只需要在a之後空1個位元組就可以存放c。所以4+2+2=8.
當然,可以不採取預設的對齊方式,可以手工修改任意位元組對齊,這個只是修改編譯器的對齊方式,只是改變了編譯出來的資料的排列方式而已,cpu依舊是按照4位元組訪問的。
人工修改位元組對齊方式有2種方式:
1、#pragma pack(n)與#pragma pack() n位元組對齊如:
#pragma pack (2) /*指定按2位元組對齊*/
struct c
;#pragma pack () /*取消指定對齊,恢復預設對齊*/
sizeof(struct c)值就變為8。
2、__attribute((aligned (n)))與__attribute__((packed))
使用如下:
struct a
__attrubute__ ((aligned(1)));
1位元組對齊,則sizeof(a)=15。
struct a
__attrubute__ ((packed));
取消結構在編譯過程中的優化對齊,按照實際占用位元組數進行對齊,是gcc特有的語法。
問:什麼時候需要手動設定對齊方式呢?
答:實際工程中,當在不同cpu下,設計通訊協議時,或編寫硬體驅動程式時(需要用結構體來描述暫存器結構),需要手動設定。即使看起來就自然對齊的也要手動對齊,以免不同的編譯器生成的**不一樣。
C 位元組對齊問題
關於c 位元組對齊問題 關於c c 的位元組對齊 這兩天寫解析swf檔案的程式,在結構體指標和從檔案中讀出來的進行轉換的時候遇到一些問題,就是有乙個struct a,例如 struct a char flag int length int id 然後乙個飄逸的 struct a a struct a...
C 位元組對齊問題
關於c 位元組對齊問題 關於c c 的位元組對齊 這兩天寫解析swf檔案的程式,在結構體指標和從檔案裡讀出來的進行轉換的時候遇到一些問題,就是有乙個struct a,比如 struct a char flag int length int id 然後乙個飄逸的 struct a a struct a...
c 記憶體中位元組對齊問題詳解
c 記憶體中位元組對齊問題詳解 一 什麼是位元組對齊,為什麼要對齊?現代計算機中記憶體空間都是按照byte劃分的,從理論上講似乎對任何型別的變數的訪問可以從任何位址開始,但實際情況是在訪問特定型別變數的時候經常在特 定的記憶體位址訪問,這就需要各種型別資料按照一定的規則在空間上排列,而不是順序的乙個...