有些信息在存儲(chǔ)時(shí),并不需要占用一個(gè)完整的字節(jié),而只需占幾個(gè)或一個(gè)二進(jìn)制位。例如在存放一個(gè)開(kāi)關(guān)量時(shí),只有 0 和 1 兩種狀態(tài),用 1 位二進(jìn)位即可。為了節(jié)省存儲(chǔ)空間,并使處理簡(jiǎn)便,C 語(yǔ)言又提供了一種數(shù)據(jù)結(jié)構(gòu),稱為"位域"或"位段"。
所謂"位域"是把一個(gè)字節(jié)中的二進(jìn)位劃分為幾個(gè)不同的區(qū)域,并說(shuō)明每個(gè)區(qū)域的位數(shù)。每個(gè)域有一個(gè)域名,允許在程序中按域名進(jìn)行操作。這樣就可以把幾個(gè)不同的對(duì)象用一個(gè)字節(jié)的二進(jìn)制位域來(lái)表示。
典型的實(shí)例:
用 1 位二進(jìn)位存放一個(gè)開(kāi)關(guān)量時(shí),只有 0 和 1 兩種狀態(tài)。
讀取外部文件格式——可以讀取非標(biāo)準(zhǔn)的文件格式。例如:9 位的整數(shù)。
位域的定義和位域變量的說(shuō)明
位域定義與結(jié)構(gòu)定義相仿,其形式為:
其中位域列表的形式為:
類型說(shuō)明符位域名:位域長(zhǎng)度
例如:
說(shuō)明 data 為 bs 變量,共占兩個(gè)字節(jié)。其中位域 a 占 8 位,位域 b 占 2 位,位域 c 占 6 位。
讓我們?cè)賮?lái)看一個(gè)實(shí)例:
在這里,packed_struct 包含了 6 個(gè)成員:四個(gè) 1 位的標(biāo)識(shí)符 f1..f4、一個(gè) 4 位的 type 和一個(gè) 9 位的 my_int。
對(duì)于位域的定義尚有以下幾點(diǎn)說(shuō)明:
一個(gè)位域必須存儲(chǔ)在同一個(gè)字節(jié)中,不能跨兩個(gè)字節(jié)。如一個(gè)字節(jié)所剩空間不夠存放另一位域時(shí),應(yīng)從下一單元起存放該位域。也可以有意使某位域從下一單元開(kāi)始。例如:
在這個(gè)位域定義中,a 占第一字節(jié)的 4 位,后 4 位填 0 表示不使用,b 從第二字節(jié)開(kāi)始,占用 4 位,c 占用 4 位。
由于位域不允許跨兩個(gè)字節(jié),因此位域的長(zhǎng)度不能大于一個(gè)字節(jié)的長(zhǎng)度,也就是說(shuō)不能超過(guò)8位二進(jìn)位。如果最大長(zhǎng)度大于計(jì)算機(jī)的整數(shù)字長(zhǎng),一些編譯器可能會(huì)允許域的內(nèi)存重疊,另外一些編譯器可能會(huì)把大于一個(gè)域的部分存儲(chǔ)在下一個(gè)字中。
位域可以是無(wú)名位域,這時(shí)它只用來(lái)作填充或調(diào)整位置。無(wú)名的位域是不能使用的。例如:
從以上分析可以看出,位域在本質(zhì)上就是一種結(jié)構(gòu)類型,不過(guò)其成員是按二進(jìn)位分配的。
位域的使用
位域的使用和結(jié)構(gòu)成員的使用相同,其一般形式為:
位域變量名.位域名位域變量名->位域名
位域允許用各種格式輸出。
請(qǐng)看下面的實(shí)例:
上例程序中定義了位域結(jié)構(gòu) bs,三個(gè)位域?yàn)?a、b、c。說(shuō)明了 bs 類型的變量 bit 和指向 bs 類型的指針變量 pbit。這表示位域也是可以使用指針的。
如果程序的結(jié)構(gòu)中包含多個(gè)開(kāi)關(guān)量,只有 TRUE/FALSE 變量,如下:
這種結(jié)構(gòu)需要 8 字節(jié)的內(nèi)存空間,但在實(shí)際上,在每個(gè)變量中,我們只存儲(chǔ) 0 或 1。在這種情況下,C 語(yǔ)言提供了一種更好的利用內(nèi)存空間的方式。如果您在結(jié)構(gòu)內(nèi)使用這樣的變量,您可以定義變量的寬度來(lái)告訴編譯器,您將只使用這些字節(jié)。例如,上面的結(jié)構(gòu)可以重寫成:
現(xiàn)在,上面的結(jié)構(gòu)中,status 變量將占用 4 個(gè)字節(jié)的內(nèi)存空間,但是只有 2 位被用來(lái)存儲(chǔ)值。如果您用了 32 個(gè)變量,每一個(gè)變量寬度為 1 位,那么 status 結(jié)構(gòu)將使用 4 個(gè)字節(jié),但只要您再多用一個(gè)變量,如果使用了 33 個(gè)變量,那么它將分配內(nèi)存的下一段來(lái)存儲(chǔ)第 33 個(gè)變量,這個(gè)時(shí)候就開(kāi)始使用 8 個(gè)字節(jié)。讓我們看看下面的實(shí)例來(lái)理解這個(gè)概念:
當(dāng)上面的代碼被編譯和執(zhí)行時(shí),它會(huì)產(chǎn)生下列結(jié)果:
位域聲明
在結(jié)構(gòu)內(nèi)聲明位域的形式如下:
下面是有關(guān)位域中變量元素的描述:
元素 | 描述 |
---|---|
type | 整數(shù)類型,決定了如何解釋位域的值。類型可以是整型、有符號(hào)整型、無(wú)符號(hào)整型。 |
member_name | 位域的名稱。 |
width | 位域中位的數(shù)量。寬度必須小于或等于指定類型的位寬度。 |
帶有預(yù)定義寬度的變量被稱為位域。位域可以存儲(chǔ)多于 1 位的數(shù),例如,需要一個(gè)變量來(lái)存儲(chǔ)從 0 到 7 的值,您可以定義一個(gè)寬度為 3 位的位域,如下:
上面的結(jié)構(gòu)定義指示 C 編譯器,age 變量將只使用 3 位來(lái)存儲(chǔ)這個(gè)值,如果您試圖使用超過(guò) 3 位,則無(wú)法完成。讓我們來(lái)看下面的實(shí)例:
當(dāng)上面的代碼被編譯時(shí),它會(huì)帶有警告,當(dāng)上面的代碼被執(zhí)行時(shí),它會(huì)產(chǎn)生下列結(jié)果:
Sizeof(Age):4Age.age :4Age.age :7Age.age :0
-
二進(jìn)制
+關(guān)注
關(guān)注
2文章
796瀏覽量
41757 -
C語(yǔ)言
+關(guān)注
關(guān)注
180文章
7614瀏覽量
137724
原文標(biāo)題:C語(yǔ)言中的位域
文章出處:【微信號(hào):c-stm32,微信公眾號(hào):STM32嵌入式開(kāi)發(fā)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論