位段以位為單位定義結(jié)構(gòu)體(或共用體)中成員所占存儲(chǔ)空間的長(zhǎng)度。
含有位段的結(jié)構(gòu)體類(lèi)型稱(chēng)為位段結(jié)構(gòu)。
位段結(jié)構(gòu)也是一種結(jié)構(gòu)體類(lèi)型,只不過(guò)其中含有以位為單位定義存儲(chǔ)長(zhǎng)度的整數(shù)類(lèi)型位段成員。采用位段結(jié)構(gòu)既節(jié)省存儲(chǔ)空間,又可方便操作。
位段結(jié)構(gòu)中位段的定義格式為:
unsigned <成員名>:<二進(jìn)制位數(shù)>
例如:
struct bytedata
{unsigned a:2; /*位段a,占2位*/
unsigned:6; /*無(wú)名位段,占6位,但不能訪(fǎng)問(wèn)*/
unsigned:0; /*無(wú)名位段,占0位,表下一位段從下一字邊界開(kāi)始*/
unsigned b:10; /*位段b,占10位*/
int i; /*成員i,從下一字邊界開(kāi)始*/
}data;
位段數(shù)據(jù)的引用:
同結(jié)構(gòu)體成員中的數(shù)據(jù)引用一樣,但應(yīng)注意位段的最大取值范圍不要超出二進(jìn)制位數(shù)定的范圍,否則超出部分會(huì)丟棄。
例如:data.a=2; 但 data.a=10;就超出范圍(a占2位,最大3)
關(guān)于位段數(shù)據(jù),注意以下幾點(diǎn):
(1)一個(gè)位段必須存儲(chǔ)在同一存儲(chǔ)單元(即字)之中,不能跨兩個(gè)單元。如果其單元空間不夠,則剩余空間不用,從下一個(gè)單元起存放該位段。
(2)可以通過(guò)定義長(zhǎng)度為0的位段的方式使下一位段從下一存儲(chǔ)單元開(kāi)始。
(3)可以定義無(wú)名位段。
(4)位段的長(zhǎng)度不能大于存儲(chǔ)單元的長(zhǎng)度。
(5)位段無(wú)地址,不能對(duì)位段進(jìn)行取地址運(yùn)算。
(6)位段可以以%d,%o,%x格式輸出。
(7)位段若出現(xiàn)在表達(dá)式中,將被系統(tǒng)自動(dòng)轉(zhuǎn)換成整數(shù)。
-------------------------------------------------------
C語(yǔ)言中用結(jié)構(gòu)實(shí)現(xiàn)位段--個(gè)人心血!值得一看哦!C語(yǔ)言中的結(jié)構(gòu)是有實(shí)現(xiàn)位段的能力的,噢!你問(wèn)它到底是什么形式是吧?這個(gè)問(wèn)題呆會(huì)給你答案。讓我們先看看位段的作用:位段是在字段的聲明后面加一個(gè)冒號(hào)以及一個(gè)表示字段位長(zhǎng)的整數(shù)來(lái)實(shí)現(xiàn)的。這種用法又被就叫作“深入邏輯元件的編程”,如果你對(duì)系統(tǒng)編程感興趣,那么這篇文章你就不應(yīng)該錯(cuò)過(guò)!
我把使用位段的幾個(gè)理由告訴大家:1、它能把長(zhǎng)度為奇數(shù)的數(shù)據(jù)包裝在一起,從而節(jié)省存儲(chǔ)的空間;2、它可以很方便地訪(fǎng)問(wèn)一個(gè)整型值的部分內(nèi)容。
首先我要提醒大家注意幾點(diǎn):1、位段成員只有三種類(lèi)型:int ,unsigned int 和signed int這三種(當(dāng)然了,int型位段是不是可以取負(fù)數(shù)不是我說(shuō)了算的,因?yàn)檫@是和你的編譯器來(lái)決定的。位段,位段,它是用來(lái)表示字段位長(zhǎng)(bit)的,它只有整型值,不會(huì)有7.2這種float類(lèi)型的,如果你說(shuō)有,那你就等于承認(rèn)了有7.2個(gè)人這個(gè)概念,當(dāng)然也沒(méi)有char這個(gè)類(lèi)型的);2、成員名后面的一個(gè)冒號(hào)和一個(gè)整數(shù),這個(gè)整數(shù)指定該位段的位長(zhǎng)(bit);3、許多編譯器把位段成員的字長(zhǎng)限制在一個(gè)int的長(zhǎng)度范圍之內(nèi);4、位段成員在內(nèi)存的實(shí)現(xiàn)是從左到右還是從右到左是由編譯器來(lái)決定的,但二者皆對(duì)。
下面我們就來(lái)看看,它到底是什么東西(我先假定大家的機(jī)器字長(zhǎng)為32位):
Struct WORD
{
unsigned int chara: 6:
unsigned int font : 7;
unsigned int maxsize : 19;
};
Struct WORD chone;
這一段是從我編寫(xiě)的一個(gè)文字格式化軟件摘下來(lái)的,它最多可以容納64(既我說(shuō)的unsigned int chara :6; 它總共是6位)個(gè)不同的字符值,可以處理128(既unsigned int font : 7 ;既2的7次方)種不同的字體,和2的19次方的單位長(zhǎng)度的字。大家都可以看到maxsize是19位,它是無(wú)法被一個(gè)short int 類(lèi)型的值所容納的,我們又可以看到其余的成員的長(zhǎng)度比char還小,這就讓我們想起讓他們共享32位機(jī)器字長(zhǎng),這就避免用一個(gè)32位的整數(shù)來(lái)表示maxsize的位段。怎么樣?還要注意的是剛才的那一段代碼在16位字長(zhǎng)的機(jī)器上是無(wú)法實(shí)現(xiàn)的,為什么?提醒你一下,看看上面提醒的第3點(diǎn),你會(huì)明白的!
你是不是發(fā)現(xiàn)這個(gè)東西沒(méi)有用啊?如果你點(diǎn)頭了,那你就錯(cuò)了!這么偉大的創(chuàng)造怎么會(huì)沒(méi)有用呢(你對(duì)系統(tǒng)編程不感興趣,相信你會(huì)改變這么一個(gè)觀(guān)點(diǎn)的)?磁盤(pán)控制器大家應(yīng)該知道吧?軟驅(qū)與它的通信我們來(lái)看看是怎么實(shí)現(xiàn)的下面是一個(gè)磁盤(pán)控制器的寄存器:
│←5→│←5→│←9→│←8→│←1→│←1→∣←1→∣←1→∣←1→∣
上面位段從左到右依次代表的含義為:5位的命令,5位的扇區(qū),9位的磁道,8位的錯(cuò)誤代碼,1位的HEAD LOADED,1位的寫(xiě)保護(hù),1位的DISK SPINNING,1位的錯(cuò)誤判斷符,還有1位的READY位。它要怎么來(lái)實(shí)現(xiàn)呢?你先自己寫(xiě)寫(xiě)看:
struct DISK_FORMAT
{
unsigned int command : 5;
unsigned sector : 5;
unsigned track : 9 ;
unsigned err_code : 8;
unsigned ishead_loaded : 1;
unsigned iswrit_protect : 1;
unsigned isdisk_spinning : 1;
unsigned iserr_ocur : 1;
undigned isready :1 ;
};
注:代碼中除了第一行使用了unsigned int 來(lái)聲明位段后就省去了int ,這是可行的,詳見(jiàn)ANCI C標(biāo)準(zhǔn)。
如果我們要對(duì)044c18bfH的地址進(jìn)行訪(fǎng)問(wèn)的話(huà),那就這樣:
#define DISK ((struct DISK_FORMAT *)0x044c18bf)
DISK->sector=fst_sector;
DISK->track=fst_track;
DISK->command=WRITE;
當(dāng)然那些都是要宏定義的哦!
我們用位段來(lái)實(shí)現(xiàn)這一目的是很方便的,其實(shí)這也可以用移位或屏蔽來(lái)實(shí)現(xiàn),你嘗試過(guò)就知道哪個(gè)更方便了!