C語(yǔ)言關(guān)于位域的概念和使用小結(jié)
LWH China shenzhen C 語(yǔ)言關(guān)于位
LWH China shenzhen C 語(yǔ)言關(guān)于位域的概念和使用小結(jié)
--------------- 2013.05
有些信息在存儲(chǔ)時(shí),并不需要占用一個(gè)完整的字節(jié),而只需占幾個(gè)或一個(gè)二進(jìn)制位。例如在存放一個(gè)開(kāi)關(guān)量時(shí),只有0和1兩種狀態(tài),用一位二進(jìn)位即可。為了節(jié)省存儲(chǔ)空間,并使處理簡(jiǎn)便,C 語(yǔ)言提供了一種數(shù)據(jù)結(jié)構(gòu),稱為“位域”。
所謂“位域”是把一個(gè)數(shù)據(jù)類型中的二進(jìn)位劃分為幾個(gè)不同的區(qū)域,并說(shuō)明每個(gè)區(qū)域的位數(shù)。每個(gè)域有一個(gè)域名,允許在程序中按域名進(jìn)行操作。這樣就可以把幾個(gè)不同的對(duì)象用一個(gè)數(shù)據(jù)類型的二進(jìn)制位來(lái)表示。
一、位域的定義和位域變量,其形式為:
struct 位域結(jié)構(gòu)名
{
位域列表
} 位域變量名;
位域列表的形式為: 類型說(shuō)明符 位域名 :位域長(zhǎng)度;
位域變量的說(shuō)明與結(jié)構(gòu)變量說(shuō)明的方式相同。可采用先定義后說(shuō)明,同時(shí)定義說(shuō)明或者直接說(shuō)明這三種方式。
例如: 定義bits 的位域結(jié)構(gòu),位域變量名為data :
struct bits
{
int a:4;
int b:6;
int c:4;
int d:4;
int e:14;
} data;
在上例中data 為bits 變量,共占4個(gè)字節(jié)。其中位域a 占4位,位域b 占
,LWH China shenzhen 6位,位域c 占4位, 位域d 占4位,位域e 占14位。
二、位域的定義規(guī)則
位域的定義大致具有如下規(guī)則:
1. 一個(gè)位域可以存儲(chǔ)在同一個(gè)字節(jié)中,也可以跨不同但相鄰的幾個(gè)個(gè)字節(jié)。
例如:
struct bits
{
int a:4;
int b:6;
int c:4;
int d:4;
int e:14;
} data;
,LWH China shenzhen
位域的使用和結(jié)構(gòu)體的使用相同,其一般形式為:
位域變量名·位域名
位域允許用各種格式輸出。
例如:
Int main(void)
{
struct bits
{
unsigned a:1;
unsigned b:3;
unsigned c:4;
} bit,*pbit;
bit.a=1; bit.b=7; bit.c=15;
printf( "d,d,dn ",bit.a,bit.b,bit.c);
pbit=&bit;
pbit-> a=0; pbit-> b&=3; pbit-> c|=1;
printf( "d,d,dn ",pbit-> a,pbit-> b,pbit-> c);
return 0;
}
上例程序中定義了位域結(jié)構(gòu)bsit ,三個(gè)位域?yàn)閍,b,c 。說(shuō)明了bits 類型的變量bit 和指向bits 類型的指針變量pbit 。這表示位域也是可以使用指針的。
四、位域的作用以及位域結(jié)構(gòu)體的存儲(chǔ)
位域成員不能單獨(dú)被取sizeof 值。C99規(guī)定int 、unsigned int和bool 可以作為位域類型,但編譯器幾乎都對(duì)此作了擴(kuò)展,允許其它類型類型的存在。
使用位域的主要目的是壓縮存儲(chǔ),其大致規(guī)則為:
1) 如果相鄰位域字段的類型相同,且其位寬之和小于類型的sizeof 大小,
,LWH China shenzhen 則后面的字段將緊鄰前一個(gè)字段存儲(chǔ),直到不能容納為止;
2) 如果相鄰位域字段的類型相同,但其位寬之和大于類型的sizeof 大小,則后面的字段將從新的存儲(chǔ)單元開(kāi)始,其偏移量為其類型大小的整數(shù)倍;
3) 如果相鄰的位域字段的類型不同,則各編譯器的具體實(shí)現(xiàn)有差異,VC6采取不壓縮方式,Dev-C 采取壓縮方式;
4) 如果位域字段之間穿插著非位域字段,則不進(jìn)行壓縮;
5) 整個(gè)結(jié)構(gòu)體的總大小為最寬基本類型成員大小的整數(shù)倍。
五、位域結(jié)構(gòu)的位域存儲(chǔ)順序問(wèn)題
我們知道字節(jié)存儲(chǔ)順序有高字節(jié)優(yōu)先的big-endian 大端存儲(chǔ)法(高字節(jié)數(shù)據(jù)放在低字節(jié)地址處)和低字節(jié)優(yōu)先的little-endian 小端存儲(chǔ)法,無(wú)論使用大端法還是小端法,都不存在技術(shù)原因,只是涉及到處理器廠商的立場(chǎng)和習(xí)慣。INTEL 的X86平臺(tái)使用小端法,IBM 、 Motorola 、Sun Microsystem的大多數(shù)微處理器則使用大端法,還有部分微處理器可以由用戶自己設(shè)置是使用大端法還是小端法,如ARM 、MIPS 、PowerPC 等。
位域在存儲(chǔ)時(shí)的順序和它的編譯器有關(guān),一般是先申請(qǐng)的放在低位。
程序舉例如下:
#include
void main()
{
} data; struct bits { int a :4; int b :6; int c :4; int d :4; int e :14;
,LWH China shenzhen
} data.a=1; data.b=19; data.c=1; data.d=2; data.e=0; printf("xn",data); printf("dn",sizeof(data));
其輸出結(jié)果為:
即結(jié)構(gòu)體成員申請(qǐng)是按照順序從低地址開(kāi)始。所以上邊結(jié)構(gòu)體在內(nèi)存中數(shù)據(jù)的排列順序?yàn)?/p>
高地址 低地址
data.e=0; data.d=2; data.c=1; data.b=19; data.a=1;
限于個(gè)人知識(shí)有限,如有紕漏敬請(qǐng)見(jiàn)諒與斧正。