• 正文
    • 1 結(jié)構(gòu)體位域
    • 2 __attribute__((packed))
    • 3 聯(lián)合使用
  • 相關(guān)推薦
申請入駐 產(chǎn)業(yè)圖譜

結(jié)構(gòu)體位域和__attribute__ ((__packed__))一起用

02/03 08:55
1276
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

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),就可以使用位域,解析也方便。

struct test{

unsigned char test1:1;

unsigned char test2:1;

unsigned char test3:1;

unsigned char test4:1

unsigned char test5:1;

unsigned char test6:1;
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大小,則后面的字段將從新的存儲單元開始。

struct test{
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ù)的目的了。

struct sbus_test

{

unsigned int channel1: 11;

unsigned int channel2: 11;

unsigned int channel3: 11;

unsigned int channel4: 11;

unsigned int channel5: 11;

...

} __attribute__ ((__packed__));

使用__attribute__ ((__packed__))處理,是可以使數(shù)據(jù)一個挨著一個,直接讀取數(shù)據(jù)了。對于一些這種特殊協(xié)議的,這樣聯(lián)合使用比較方便。

 

相關(guān)推薦