編程時,有些數據值的範圍可能很小,即使使用基本數據類型存儲也顯得非常奢侈浪費。這時可以把若干個數據緊湊地“壓縮”“打包”在一個存儲空間之內。實現這種“壓縮”“打包”的技術手段就是位段(Bit Field)。
位段的引用和結構體成員的引用相同。
基本介紹
- 中文名:段引用串
- 外文名:Section of the reference list
- 定義:對位段進行引用
- 類型:位段
- 系統:計算機
- 套用學科:計算機原理
位段的含義,定義位段,位段的性質,位段的引用,位段引用的注意事項,位段的優點,
位段的含義
編程時,有些數據值的範圍可能很小,即使使用基本數據類型存儲也顯得非常奢侈浪費。這時可以把若干個數據緊湊地“壓縮”“打包”在一個存儲空間之內。實現這種“壓縮”“打包”的技術手段就是位段(Bit Field)。
所謂位段是指在結構體或共用體中被指定了擁有特定位數的成員,這些成員必須是整數類型的。例如,考慮一個存儲年、月、日的數據類型,由於年只需要4位十進制數,折算成二進制需要14位;月的數值範圍在1~12之間,所以只需要4位二進制數;日的取值範圍在1~3l之間,所以需要5位二進制數。這時可以考慮採用下面的數據結構:
struct riqi {
int nian :14;
int yue :4;
int ri :5;
};
成員名稱後面“:”後的數字表示的是該成員所占的位數。這樣的存儲方案可以極大地節約記憶體。
定義位段
在結構體或共用體類型中定義位段成員的一般方法是:
數據類型[成員名稱]:數據寬度;
這裡數據據類型可以是signed int、unsigned int、int,這三種類型是標準規定的,C99還容許_Bool類型。有些編譯器在此基礎上還允許其他類型,比如char類型;數據寬度必須是一個非負的整數類型常量表達式。這個數據寬度不允許過大.一般來說,通常以計算機的字長為限;成員名稱是可以省略的,但這樣的成員在代碼中是無法引用的,其作用是在數據之問起到間隔或填充的作用,通常被叫做無名位段。
如果一個無名位段的數據寬度為0。表示的含義是下一位段需要存放到下一個存儲單元,但這種存儲單元究竟以什麼為單位很難一概而淪,通常是由編譯器自行定義的,大多數情況下是指一個計算機字。位段成員同樣不能跨越存儲單元的邊界。如果遇到一個存儲單元中剩餘的位數不夠存儲下一個位段的情況,編譯器會將這個位段安排在下一個存儲單元之中。
位段的性質
位段的值(右值)可以參與運算,運算時一律轉換為signed類型或unsigned類型,但是int類型的位段很難說是signed類型還是unsigned類型的,正如char類型由實現定義為signed char類型或unsigned char類型一樣。
如果編譯器規定char類型為signed char類型,那么int類型的位段也是signed類型的;反之,如果編譯器規定char類型為unsigned char類型,那么int類型的位段也是unsigned類型的。
位段成員可以被賦值,但基本上無法把位段成員當作左值,因為無法給出位段的位置的C語言表達。位段無法作為左值參與求長度(“sizeof”)、求指針(“&.”)等左值才能參與的運算,但可以進行自增、自減這種運算。
由於C語言無法表達位段的記憶體位置,所以也不可以構造位段數組。
可以用%d、%x、%u和%o等格式轉換說明以整數形式輸出位段的值。但是由於位段成員無法進行一元求指針(“&.”)運算,所以無法直接通過凋用scanf()函式輸入位段的數據。
位段的引用
對位段的引用方法與引用結構體變數中的成員是相同的,比如已經定義了位段如下:
struct packed_data
{unsigned int a:3;/*占3位*/
unsigned int b:1;/*占1位*/
UnSigned int c:3;/*占3位*/
unsigned int d:1;/*占1位*/
}x;
(1)可以用以下的方法引用位段。例如:
x.a
x.b
x.c
x.d
(2)允許對位段進行如下的賦值。例如:
x.a=2;
x.b=1;
x.c=7;
x.d=0;
(3)可以用指針變數指向一個成員為位段的結構體變數,可以引用此結構體變數的地址,也可以通過指針變數來引用位段。例如:
struct packed_data x,*p;
p=&x; /*使指針p指向結構體變數x*/
printf(”%d”,p一>a); /*輸出指針P所指結構體中的位段a*/
(4)位段可以在數值表達式中引用,它會被系統自動地轉換成整型。例如:
x.c+5/x.b
(5)位段可以用整型格式符輸出。例如:
printf(”%d,%d,%d”,x.a,x.b,x.c);
也可以用%u、%o、%x等格式符輸出。
位段引用的注意事項
①位段可以初始化,形式與結構體變數賦初值相同,位段也可以進行賦值:|
例如:
data.b=2;
賦值時應注意位段的取值範圍,例如:
data.c=2;
就會產生錯誤的結果。因為data.c只占1位,只能取值0或1,對於賦值語句:data.c=2,;系統並不報錯,而是自動截取所賦值的低位,2的二進制碼是10,取低一位為0,所以data.c的值為0。
②位段可以進行算術運算,系統自動將其轉換成整型數。
例如:
data.b=5;
data.c=1;
data.a=data.b+data.c;
③可以用整型格式符(%d、%o、%x、%u)進行輸出
例如:
printf(”%d\n”,data.a);
④不能對位段求地址。
由於位段沒有地址,所以不能對位段求地址,也不能通過scanf()數給位段賦值,不能用指針變數指向位段。
位段的優點
位段在C語言編程中是很有用的,主要表現為:
(1)使用戶能方便地訪問一個位元組中的有關位,從而能更有力地控制程式的運行。這在其他高級語言中是無法實現的。
(2)用位段可以節省存儲空間。把幾個數據放在同一位元組中,如“真”和“假”(即0和1),這樣的信息只需一位就可以存放了。
(3)對位段的操作比用位運算方便,而且可移植性高,效率高。