深度C理解位域
深度C 理解位域(fylxaut 著) 有些信息在存儲時,并不需要占用一個完整的字節(jié), 而只需占幾個或一個二進(jìn)制位。例如在存放一個開關(guān)量時,只有0和1 兩種狀態(tài),用一位二進(jìn)位即可。為了節(jié)省存儲空間,并
深度C 理解位域(fylxaut 著) 有些信息在存儲時,并不需要占用一個完整的字節(jié), 而只需占幾個或一個二進(jìn)制位。例如在存放一個開關(guān)量時,只有0和1 兩種狀態(tài),用一位二進(jìn)位即可。為了節(jié)省存儲空間,并使處理簡便,C語言又提供了一種數(shù)據(jù)結(jié)構(gòu),稱為“位域”或“位段”。所謂“位域”是把一個字節(jié)中的二進(jìn)位劃分為幾個不同的區(qū)域,并說明每個區(qū)域的位數(shù)。每個域有一個域名,允許在程序中按域名進(jìn)行操作。 這樣就可以把幾個不同的對象用一個字節(jié)的二進(jìn)制位域來表示。
一、位域的定義和位域變量的說明位域定義與結(jié)構(gòu)定義相仿,其形式為: struct 位域結(jié)構(gòu)名
{ 位域列表 };
其中位域列表的形式為: 類型說明符 位域名:位域長度
例如:
struct bs
{
int a:8;
int b:2;
int c:6;
};
//////////////////////////////////////////////////////////////////////////////////////////////////////
struct foo1 {
int a : 1;
int : 2;/空域
short c : 1;

};
在foo 結(jié)構(gòu)體的定義中,成員a 雖然類型為int ,但是它僅僅占據(jù)著4個字節(jié)中的一個bit 的空間;類似b 占據(jù)2個bit 空間,但是b 到底是占據(jù)第一個int 的2個bit 空間呢還是第二個int 的2個bit 空間呢?這里實際上也涉及到如何對齊帶有' 位域' 的結(jié)構(gòu)體這樣一個問題。我們來分析一下。
struct foo2 {
char a : 2;
,char b : 3;
char c : 1;

};
struct foo3 {
char a : 2;
char b : 3;
char c : 7;

};
顯然都不是我們期望的,如果按照正常的內(nèi)存對齊規(guī)則,這兩個結(jié)構(gòu)體大小均應(yīng)該為3才對,那么問題出在哪了呢?首先通過這種現(xiàn)象我們可以肯定的是:帶有' 位域' 的結(jié)構(gòu)體并不是按照每個域?qū)R的,而是將一些位域成員' 捆綁' 在一起做對齊的。
1) 以foo2為例,這個結(jié)構(gòu)體中所有的成員都是char 型的,而且三個位域占用的總空間為6 bit < 8 bit(1 byte),這時編譯器會將這三個成員' 捆綁' 在一起做對齊,并且以最小空間作代價,這就是為什么我們得到sizeof(struct foo2) = 1這樣的結(jié)果的原因了。
2) 再看看foo3這個結(jié)構(gòu)體,同foo2一樣,三個成員類型也都是char 型,但是三個成員位域所占空間之和為9 bit > 8 bit(1 byte),這里位域是不能跨越兩個成員基本類型空間的,這時編譯器將a 和b 兩個成員' 捆綁' 按照char 做對齊,而c 單獨拿出來以char 類型做對齊,這樣實際上在b 和c 之間出現(xiàn)了空隙,但這也是最節(jié)省空間的方法了。我們再看一種結(jié)構(gòu)體定義:
struct foo4 {
char a : 2;
char b : 3;
int c : 1;
};

在foo4中雖然三個位域所占用空間之和為6 bit < 8 bit(1 byte) ,但是由于char 和int 的對齊系數(shù)是不同的,是不能捆綁在一起,那是不是a 、b 捆綁在一起按照char 對齊,c 單獨按照int 對齊呢。