C 位域
C 位域
如果程式的結構中包含多個開關量,只有 TRUE/FALSE 變數,如下:
struct { unsigned int widthValidated; unsigned int heightValidated; } status;
這種結構需要 8 位元組的記憶體空間,但在實際上,在每個變數中,我們只儲存 0 或 1。在這種情況下,C 語言提供了一種更好的利用記憶體空間的方式。如果您在結構內使用這樣的變數,您可以定義變數的寬度來告訴編譯器,您將只使用這些位元組。例如,上面的結構可以重寫成:
struct { unsigned int widthValidated : 1; unsigned int heightValidated : 1; } status;
現在,上面的結構中,status 變數將佔用 4 個位元組的記憶體空間,但是隻有 2 位被用來儲存值。如果您用了 32 個變數,每一個變數寬度為 1 位,那麼 status 結構將使用 4 個位元組,但只要您再多用一個變數,如果使用了 33 個變數,那麼它將分配記憶體的下一段來儲存第 33 個變數,這個時候就開始使用 8 個位元組。讓我們看看下面的例項來理解這個概念:
例項
當上面的程式碼被編譯和執行時,它會產生下列結果:
Memory size occupied by status1 : 8 Memory size occupied by status2 : 4
位域宣告
有些資訊在儲存時,並不需要佔用一個完整的位元組,而只需佔幾個或一個二進位制位。例如在存放一個開關量時,只有 0 和 1 兩種狀態,用 1 位二進位即可。為了節省儲存空間,並使處理簡便,C 語言又提供了一種資料結構,稱為"位域"或"位段"。
所謂"位域"是把一個位元組中的二進位劃分為幾個不同的區域,並說明每個區域的位數。每個域有一個域名,允許在程式中按域名進行操作。這樣就可以把幾個不同的物件用一個位元組的二進位制位域來表示。
典型的例項:
- 用 1 位二進位存放一個開關量時,只有 0 和 1 兩種狀態。
- 讀取外部檔案格式——可以讀取非標準的檔案格式。例如:9 位的整數。
位域的定義和位域變數的說明
位域定義與結構定義相仿,其形式為:
struct 位域結構名 { 位域列表 };
其中位域列表的形式為:
type [member_name] : width ;
下面是有關位域中變數元素的描述:
元素 | 描述 |
---|---|
type | 只能為 int(整型),unsigned int(無符號整型),signed int(有符號整型) 三種類型,決定了如何解釋位域的值。 |
member_name | 位域的名稱。 |
width | 位域中位的數量。寬度必須小於或等於指定型別的位寬度。 |
帶有預定義寬度的變數被稱為位域。位域可以儲存多於 1 位的數,例如,需要一個變數來儲存從 0 到 7 的值,您可以定義一個寬度為 3 位的位域,如下:
上面的結構定義指示 C 編譯器,age 變數將只使用 3 位來儲存這個值,如果您試圖使用超過 3 位,則無法完成。
data 為 bs 變數,共佔兩個位元組。其中位域 a 佔 8 位,位域 b 佔 2 位,位域 c 佔 6 位。
讓我們再來看一個例項:
在這裡,packed_struct 包含了 6 個成員:四個 1 位的識別符號 f1..f4、一個 4 位的 type 和一個 9 位的 my_int。
讓我們來看下面的例項:
例項
當上面的程式碼被編譯時,它會帶有警告,當上面的程式碼被執行時,它會產生下列結果:
Sizeof( Age ) : 4 Age.age : 4 Age.age : 7 Age.age : 0
對於位域的定義尚有以下幾點說明:
-
一個位域儲存在同一個位元組中,如一個位元組所剩空間不夠存放另一位域時,則會從下一單元起存放該位域。也可以有意使某位域從下一單元開始。例如:
struct bs{ unsigned a:4; unsigned :4; /* 空域 */ unsigned b:4; /* 從下一單元開始存放 */ unsigned c:4 }在這個位域定義中,a 佔第一位元組的 4 位,後 4 位填 0 表示不使用,b 從第二位元組開始,佔用 4 位,c 佔用 4 位。
位域的寬度不能超過它所依附的資料型別的長度,成員變數都是有型別的,這個型別限制了成員變數的最大長度,: 後面的數字不能超過這個長度。
-
位域可以是無名位域,這時它只用來作填充或調整位置。無名的位域是不能使用的。例如:
struct k{ int a:1; int :2; /* 該 2 位不能使用 */ int b:3; int c:2; };
從以上分析可以看出,位域在本質上就是一種結構型別,不過其成員是按二進位分配的。
位域的使用
位域的使用和結構成員的使用相同,其一般形式為:
位域變數名.位域名 位域變數名->位域名
位域允許用各種格式輸出。
請看下面的例項:
例項
上例程式中定義了位域結構 bs,三個位域為 a、b、c。說明了 bs 型別的變數 bit 和指向 bs 型別的指標變數 pbit。這表示位域也是可以使用指標的。