1 結(jié)構(gòu)體位域
1.1 位域
位域是一種節(jié)省空間的數(shù)據(jù)結(jié)構(gòu),是把一個數(shù)據(jù)類型按照二進(jìn)制(二進(jìn)位)劃分為幾個不同的區(qū)域,并說明每個區(qū)域的位數(shù)。
比如有一個字節(jié),每一位表示一個開關(guān)狀態(tài),就可以使用位域,解析也方便。
unsigned char test7:1;
unsigned char test8:1;
這樣收到1字節(jié)數(shù)據(jù)賦值給test,解析每個位的狀態(tài)直接使用test.test1.....test.test6就可以,不需要再進(jìn)行相應(yīng)的位與操作之類的。還可以節(jié)省空間。要注意大小端,小端的test1是低位。
1.2位域的具體存儲規(guī)則如下:
1) 如果相鄰位域字段的類型相同,且其位寬之和小于類型的sizeof大小,則后面的字段將緊鄰前一個字段存儲,直到不能容納為止。
2)如果相鄰位域字段的類型相同,但其位寬之和大于類型的sizeof大小,則后面的字段將從新的存儲單元開始。
unsigned char test1:1;
unsigned char test2:4;
unsigned char test3:4;
unsigned char test4:1;
unsigned char test5:1;
unsigned char test6:1;
unsigned char test7:1;
unsigned char test8:1;
}
舉例,這個test結(jié)構(gòu)體,成員test3+test2+test1的位寬為9,大于char的8位,那從test3開始就要從第2個字節(jié)開始存。
編輯切換為居中
添加圖片注釋,不超過 140 字(可選)
3)如果相鄰的位域字段的類型不同,則各編譯器的具體實現(xiàn)有差異,不建議使用,也沒啥使用的必要。
4)如果位域字段之間穿插著非位域字段,則不進(jìn)行壓縮。
5)整個結(jié)構(gòu)體的總大小為最寬基本類型成員大小的整數(shù)倍,和普通結(jié)構(gòu)體一樣。
2 __attribute__((packed))
__attribute__ ((packed)) 的作用就是告訴編譯器取消結(jié)構(gòu)在編譯過程中的優(yōu)化對齊,按照實際占用字節(jié)數(shù)進(jìn)行對齊,是GCC特有的語法。
__attribute__關(guān)鍵字主要是用來在函數(shù)或數(shù)據(jù)聲明中設(shè)置其屬性。
3 聯(lián)合使用
對于一些特殊的協(xié)議,比如sbus,sbus一個通道占11位,那按照位域的規(guī)則,下屬代碼中的channel3就要在存儲在下一個unsigned int中了。就不滿足我們直接利用編譯器解析數(shù)據(jù)的目的了。
使用__attribute__ ((__packed__))處理,是可以使數(shù)據(jù)一個挨著一個,直接讀取數(shù)據(jù)了。對于一些這種特殊協(xié)議的,這樣聯(lián)合使用比較方便。