C语言自定义类型——位段
位段
?
目錄
位段
一、定義
二、注意事項(xiàng)
1、位段成員必須是整型家族的(int ,unsigned int ,char 等)。
2、位段成員名后可跟冒號(hào)加一個(gè)數(shù)字來表示它占有幾個(gè)比特位
三、位段的內(nèi)存分配
四、具體空間開辟(截?cái)?#xff09;
五、位段的跨平臺(tái)問題
?
C語言中有很多的自定義類型,我在以前的博客中已經(jīng)講過了結(jié)構(gòu)體和結(jié)構(gòu)體的內(nèi)存對(duì)齊,現(xiàn)在我們來講另一個(gè)自定義類型,就是位段。
一、定義
位段,C語言允許在一個(gè)結(jié)構(gòu)體中以比特位為單位來指定其成員所占內(nèi)存長(zhǎng)度,這種以位為單位的成員稱為“位段”或稱“位域”( bit field) 。利用位段能夠用較少的位數(shù)存儲(chǔ)數(shù)據(jù)。
可以看出位段和結(jié)構(gòu)體很像,下面我們引入一段代碼片段來看一下位段到底長(zhǎng)什么樣子。
struct A{int a : 2;//成員a占2個(gè)比特位int b : 5;//成員b占5個(gè)比特位int c : 10;//成員c占10個(gè)比特位int d : 30;//成員d占30個(gè)比特位 };二、注意事項(xiàng)
1、位段成員必須是整型家族的(int ,unsigned int ,char 等)。
可以看見,這里如果是float類型的成員,編譯器會(huì)直接報(bào)錯(cuò)。
整型家族的數(shù)組也不行哦,編譯器也會(huì)報(bào)錯(cuò)。
2、位段成員名后可跟冒號(hào)加一個(gè)數(shù)字來表示它占有幾個(gè)比特位
正如我們?cè)? 一、定義? 時(shí)的代碼片段,但是其實(shí)一個(gè)位段的部分成員也可以不加冒號(hào)和數(shù)字(如果全部成員都不加冒號(hào)和數(shù)字了它就變成結(jié)構(gòu)體了)。
例如上圖,我們也是不會(huì)錯(cuò)的。
三、位段的內(nèi)存分配
在window環(huán)境下的VS編譯器中,位段的內(nèi)存分配是按照這種規(guī)則的:根據(jù)首個(gè)成員變量的類型分配相應(yīng)字節(jié)的內(nèi)存(例如:首個(gè)成員是 int 類型的,則分配4個(gè)字節(jié)即32個(gè)比特位的空間大小),然后根據(jù)成員的實(shí)際大小(也就是:后面的數(shù)字)來填充這個(gè)已經(jīng)分配的空間,若剩余的空間不夠了,則繼續(xù)根據(jù)成員類型依次分配內(nèi)存并且填充(分配內(nèi)存時(shí)要注意內(nèi)存對(duì)齊,如果不知道什么是內(nèi)存對(duì)齊,可以看我以前寫的博客,填充時(shí)不用對(duì)齊),直到該位段的最后一個(gè)成員,需要注意的是,整個(gè)位段的大小是成員類型大小中最大值的整數(shù)倍。
上面的概念過于復(fù)雜,我們來看一個(gè)例子:
第一步,分配,根據(jù)第一個(gè)成員的類型分配4字節(jié)即32位大小的內(nèi)存;
第二步,填充,因?yàn)閍,b,c成員的大小加起來為27位,而d成員為6位,所以這塊被分配的內(nèi)存只能填充a,b,c(這里的填充是反向填充,即從該區(qū)域的最后端開始依次填充a,b,c);
第三步,分配,根據(jù)接下來的成員也就是 char 型的 d 分配一個(gè)字節(jié)8個(gè)比特位的空間,根據(jù)內(nèi)存對(duì)齊判斷,該空間緊貼上一個(gè)分配的空間即可;
第四步,填充,這塊空間只夠填充成員 d ;
第五步,分配,并判斷內(nèi)存對(duì)齊,應(yīng)根據(jù) int 型變量 e 分配4個(gè)字節(jié)的空間,但根據(jù)內(nèi)存對(duì)齊這段被分配的空間不能緊挨著成員 d ,應(yīng)該間隔3個(gè)字節(jié)再分配(對(duì)齊到該成員對(duì)齊數(shù)整數(shù)倍的位置上);
第六步,填充,這個(gè)空間只夠填充成員 e 占用其中的30位;
第七步,根據(jù)成員 f?的 char 型分配一個(gè)字節(jié)的空間,根據(jù)內(nèi)存對(duì)齊規(guī)則,該區(qū)域可以緊貼上一個(gè)區(qū)域,然后將最后一個(gè)成員填充進(jìn)去;
第八步,根據(jù)內(nèi)存對(duì)齊規(guī)則的最后一條,也就是整個(gè)位段的大小是成員類型大小中最大值的整數(shù)倍,所以我們必須還要在余出3個(gè)字節(jié);
所以,位段A的內(nèi)存分布情況為下圖:
sizeof(struct A)=5+3+4+1+3=16字節(jié)。
下面來驗(yàn)證一下:
四、具體空間開辟(截?cái)?#xff09;
看一個(gè)具體的例子:
struct S{char a : 3;char b : 4;char c : 5;char d : 4; };struct S s = { 0 }; s.a = 10; s.b = 12; s.c = 3; s.d = 4;由于位段的成員的大小被重新分配,例如成員 a 占3個(gè)比特位,它的范圍應(yīng)該是 0 到 7 ,而這里給 a 賦值為10,應(yīng)該如何處理呢?這里的操作我稱作為截?cái)?/p>
請(qǐng)看下面我畫出的內(nèi)存圖,更為直觀
驗(yàn)證:這是VS中內(nèi)存的部分
和我們的分析一致。
五、位段的跨平臺(tái)問題
位段在不同的平臺(tái)上有不同的規(guī)則:
1、int 位段被當(dāng)成有符號(hào)數(shù)還是無符號(hào)數(shù)是不確定的。
2、位段中的成員從左到右分配還是從右到左分配是不確定的。
3、當(dāng)一個(gè)結(jié)構(gòu)包含兩個(gè)位段,第二個(gè)位段成員比較大,無法容納第一個(gè)位段剩余的位時(shí),是舍棄剩余的位還是利用,也是不確定的。
所以跟結(jié)構(gòu)體相比,位段更節(jié)省空間,但是有跨平臺(tái)的問題。
?
?
這就是今天和大家分享的內(nèi)容了,希望大家一起提高,共同進(jìn)步!!!
?
?
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的C语言自定义类型——位段的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于mfc实现画图软件
- 下一篇: OpenSSL笔记-PKCS#1和PKC