參考:
三步解決c語言中struct位元組對齊問題:
結構體對齊規則:
先介紹三個概念:自身對齊值、指定對齊值、有效對齊值。
自身對齊值:資料型別本身的對齊值,例如char型別的自身對齊值是1,short型別是2;
指定對齊值:編譯器或程式設計師指定的對齊值,32位微控制器的指定對齊值預設是4;
有效對齊值:自身對齊值和指定對齊值中較小的那個。
1.先確定指定對齊值,其由以下三個因素決定
(1) cpu週期
win vs qt 預設8位元組對齊
linux 32位 預設4位元組對齊,64位預設8位元組對齊
(2) 結構體最大成員(基本資料型別變數)
(3) 預編譯指令#pragma pack(n)手動設定 n--只能填1 2 4 8 16
2.除結構體的第乙個成員外,其他所有的成員的位址相對於結構體位址(即它首個成員的位址)的偏移量必須為該型別的有效對齊值(自身對齊值和指定對齊值中較小的那個)
3. 結構體的整體有效對齊值是其最大資料成員的自身對齊值;
上面三步即是萬能公式,下面看實際例子(linux 64系統下):
上面nums中,沒有手動設定對齊單位,linux64系統的預設對齊單位是8位元組,結構體nums的最大成員double d佔8個位元組,故實際對齊位元組是二者最小,即8位元組。
char a放在結構體的起始位址;
short b佔2個位元組,2小於實際對齊位元組8,故b的起始位址相對於a的起始位址的偏移量須為2的整數倍個位元組;
int c佔4個位元組,4小於實際對齊位元組8,故c 起始位址相對於a的起始位址的偏移量須為4的整數倍個位元組;
double d佔8個位元組,8與實際對齊位元組8相等,故d的起始位址相對於a的起始位址的偏移量須為8的整數倍個位元組;
所以nums所佔空間如下: 1(a)+1(浪費的空間,由b的起始位址決定這1位元組必須騰出)+2(b)+4(c)+8(d)=16個位元組
2.在上面結構體最後新增乙個char陣列,再看情況:
到成員double d為止,結構體nums佔的空間是16,上面已經分析過,然後後面是乙個char型陣列,陣列的型別是char[13],並不是基本資料型別,這裡仍然當做13個char型變數來處理,char佔1個位元組,小於實際對齊位元組8,所以這13個char型變數可以直接挨著double d後面放(最後結果看起來也就相當於整個陣列挨著double d放置);所以總的空間情況是:1(a)+1(浪費空間)+2(b)+4(c)+8(d)+13(arr)=29;但29並不滿足上面三步走的最後一步:「整個結構體的大小必須是實際對齊單位的整數倍」,所以29+5(浪費空間)=32,所以最後nums的空間情況是1(a)+1(浪費空間)+2(b)+4(c)+8(d)+13(arr)+5(浪費空間)=32位元組
另外結構體巢狀結構體的位元組對齊和上面原理一樣,唯一要注意的是子結構體的起始位址與母結構體的起位址之間的距離必須是子結構體最大成員或者實際對齊單位(還是取兩者小的那個)的整數倍。
輸出結果:
答:最長資料型別的有效對齊
實驗:window64,指定對齊8位元組
typedef
struct
datatype0
type0;
typedef
struct
datatype1
type1;
intmain()
執行結果:
如果為指定對齊,type0,1都應該是8,顯然不是指定對齊方式。
資料型別之結構體
結構體是構造資料型別的一種 在c語言中,結構體是一種非常重要的資料型別。封裝多個不同型別的元素,作為互動的乙個介面 互動這塊,結構體變數可以作為資料結構中的乙個節點,可以作為網路通訊中傳送的訊息的封裝,可以作為核心中檔案屬性的封裝,可以作為驅動中對裝置檔案操作的封裝.也就是說,驅動,核心,應用方面都...
c 中的構造資料型別 結構體
無論是基本資料型別還是陣列型別都僅僅描述了事物某一方面的特性,但是,一種事物往往具有多方面的屬性,如乙個同學有學號,姓名,性別,年齡等屬性。c 中的構造資料型別簡單點理解就是將乙個或者幾個資料型別組合起來的。在回顧一下比如int float double等,叫做基礎型別,或內建型別,而由這些型別做成...
列舉資料型別 struct結構體
列舉通常用來表示一組常量 列舉類似於單項選擇題,只能多軒逸 列舉即可以放在類中也可以放在類外 使用關鍵字enum宣告列舉型別 enum week中間用逗號 半形 間隔,最後一位成員可加可不加 為了區分是最後一位成員,一般不加 列舉預設資料型別為int型,如上 mnday 0 sunday 6 定義乙...