有些信息在存儲時,並不需要占用一個完整的字節, 而只需占幾個或一個二進制位。例如在存放一個開關量時,只有0和1 兩種狀態, 用一位二進位即可。
為了節省存儲空間,並使處理簡便,C語言又提供了一種數據結構,稱為位域或位段。所謂位域是把一個字節中的二進位劃分為幾個不同的區域, 並說明每個區域的位數。每個域有一個域名,允許在程序中按域名進行操作。 這樣就可以把幾個不同的對象用一個字節的二進制位域
來表示。一、位域的定義和位域變量的說明位域定義與結構定義相仿,其形式為:
struct 位域結構名
{ 位域列表 };
其中位域列表的形式為: 類型說明符 位域名:位域長度
struct WbitF { unsigned int b0: 1;
unsigned char b0 :1;
unsigned char b1:1;
unsigned char b2:1;
unsigned char b3:1;
unsigned char b4:1;
unsigned char b5:1;
unsigned char b6:1;
unsigned char b7:1;
unsigned char b8:1;
unsigned char b9:1;
unsigned char b10:1;
unsigned char b11:1;
unsigned char b12:1;
unsigned char b13:1;
unsigned char b14:1;
unsigned char b15:1;
}
每個都占一位,若不夠放存入下個字節中。1共占2個字節 :1是按位存儲。
基本的成員變量就會被拆分!這個語法在初級編程中很少用到,但是在高級程序設計中不斷地被用到!
例如: struct student {
unsigned int sex : 1;
unsigned int age : 15;
};
上述結構體中的兩個成員 sex 和 age 加起來只占用了一個 unsigned int 的空間(假設 unsigned int 為 16 位)。 基本成員變量被拆分後,訪問的方法仍然和訪問沒有拆分的情況是一樣的,例如: struct student sweek; sweek.sex = MALE;// 這裡的 MALE 只能是 0 或 1 ,值不能大於 1 sweek.age = 20; 雖然拆分基本成員變量在語法上是得到支持的,但是並不等於我們想怎麼分就怎麼分,例如下面的拆分顯然是不合理的: struct student { unsigned int sex : 1; unsigned int age : 12; }; 這是因為 1+12 = 13 ,不能再組合成一個基本成員,不能組合成 char 、 int 或任何類型,這顯然是不能 “ 自圓其說 ” 的。
keil中不支持二進制數據,如0b0101,這樣編譯器無法通過。在使用位域時,會過多的使用位操作,如& | << >>等操作。
關於字節和位域之間的轉換,如下:
typedef struct {
u8 model_flag :2;
u8 fan_rank :2;
u8 windsweeper :1;
u8 :3;
}set_status
set_status set_info;
set_info = buff[1];//把一個字節賦給位域結構體
這裡需要注意的是,結構體剛好設置為一個字節,可以容納buff[1]這個字節。特別注意的是:位域結構體中的各個變量的分配時從該字節的低位開始的。若buff為0110 1010,那麼model_flag為 10,fan_rank為 10,windsweeper為 0,未用的三個位是011。