C語(yǔ)言位段(位域)機(jī)制結(jié)構(gòu)體的特殊實(shí)現(xiàn)及解析
概念
什么是位段?
位段又稱為位域,C語(yǔ)言允許在一個(gè)結(jié)構(gòu)體中以位為單位來(lái)指定其成員所占內(nèi)存長(zhǎng)度,這種以位為單位的成員就叫做稱為位段( bit field) 。利用位段能夠用較少的位數(shù)存儲(chǔ)數(shù)據(jù)達(dá)到節(jié)省空間的目的。
位段是結(jié)構(gòu)體特有的,所以聲明是和結(jié)構(gòu)是類似的,但有兩個(gè)不同:
1. 位段成員必須是 int ,unsigned int,signed int
2. 位段成員名后邊結(jié)構(gòu)包括一個(gè)冒號(hào)和整型數(shù)字
舉個(gè)栗子:
struct haha { unsigned int ch : 8; //8位 unsigned int chh : 6; //6位 unsigned int chhh : 18; //18位 }; struct haha dest;
內(nèi)存分配
這里的 haha 就是一個(gè)位段的類型,這個(gè)神神秘秘的位段咱不常見(jiàn),那么他的大小怎么算的呢?其實(shí)和結(jié)構(gòu)體是一樣的:
struct arr { int a:2; int b:5; int c:10; int d:30; }; int main() { printf("%d\n",sizeof(struct arr)); return 0; }
這里 a:2什么意思呢?
成員 a 只占 2 個(gè)比特位,后面同理,既然這樣,那我們總計(jì) 47 比特位,也就是 6 個(gè)字節(jié) 48 個(gè)比特位已經(jīng)足夠了,那為什么又是 8 呢?位段的內(nèi)存分配到底是怎樣的?
這里千萬(wàn)不要犯低級(jí)錯(cuò)誤誤認(rèn)為他的大小就是 47 個(gè)比特位,和前一篇博客敘述原理相同,因?yàn)槎际?int 類型,所有成員會(huì)向 int 看齊,int 是四字節(jié),默認(rèn) 8 字節(jié),對(duì)齊數(shù)取 4 字節(jié),a+b < 1字節(jié),合并申請(qǐng) 1 字節(jié)空間,后面都需要獨(dú)立申請(qǐng)空間,總計(jì) 1+2+4 = 7字節(jié),結(jié)構(gòu)體大小必須是最大對(duì)齊數(shù)整數(shù)倍,取 4 的整數(shù)倍就是 8,因此為 8 字節(jié)。
位段跨平臺(tái)問(wèn)題
我們細(xì)想剛剛這種機(jī)制,a,b,c,d 分別為 2,5,10,30 比特位,而我一個(gè)字節(jié)是 8 個(gè)比特位,假若在給 a 分配了 1 字節(jié)后,還剩 6 比特位,這 6 個(gè)位子我要不要讓給二哥 b 成員來(lái)享用呢?==我是一字節(jié)一字節(jié)榨干資本還是出手闊綽安排"單人房"呢?==這里就有了歧義。
要知道位段在空間上是按照需要以四字節(jié) int 或一字節(jié) char 的方式來(lái)開(kāi)辟空間,他涉及很多的不確定性因素,這就是為什么位段是不跨平臺(tái)的,注重可移植性的程序應(yīng)該避免使用位段。
有什么不確定因素呢,就好比我們剛剛提到的內(nèi)存分配問(wèn)題,這個(gè)問(wèn)題連C語(yǔ)言標(biāo)準(zhǔn)都沒(méi)有規(guī)定我到底該怎么利用,需要由具體的編譯器環(huán)境決定,編譯器環(huán)境又依賴于不同的平臺(tái)比如 Linux 是 gcc 標(biāo)準(zhǔn),VS則是 windows 標(biāo)準(zhǔn)。
我們要知道:
- 1. int 位段被當(dāng)成有符號(hào)數(shù)還是無(wú)符號(hào)數(shù)是不確定的。
- 2. 位段中最大位的數(shù)目不能確定(16位機(jī)器最大 16,32 位機(jī)器最大 32)。
- 3. 位段中成員的內(nèi)存從左到右分配還是從右向左分配標(biāo)準(zhǔn)尚未定義。
- 4. 當(dāng)一個(gè)結(jié)構(gòu)中包含兩個(gè)位段時(shí),第二個(gè)位段成員比較大,無(wú)法容納第一個(gè)位段剩余的位時(shí),是應(yīng)當(dāng)舍棄還是利用,標(biāo)準(zhǔn)尚未定義。
作用
“ 這么個(gè)玄乎的玩意兒拿來(lái)干嘛啊 ”你可能會(huì)有這樣的疑問(wèn)
我們拿上面的情景來(lái)分析一手:
int a:2; int b:5; int c:10; int d:30;
我們不分配位段時(shí),需要 16 個(gè)字節(jié),分配后只要 8 個(gè)字節(jié),其實(shí)位段就是為了節(jié)省空間,充當(dāng)個(gè)省流大師。
位段使用的前提條件就是某些細(xì)節(jié)需要非常明確,假如我成員 a 的取值只有四種狀態(tài):00,01,10,11,那我給 a 分配 2 個(gè)字節(jié)是不是就足夠了,那我就給 2 個(gè),我如果一上手啪嘰就是一個(gè) int 類型,32 個(gè)字節(jié)橫空出世,這個(gè)節(jié)省的性價(jià)比可不低哦~
當(dāng)然萬(wàn)事萬(wàn)物不可能十全十美,我?guī)湍愎?jié)省但總歸會(huì)有一定浪費(fèi),這是不可避免的??偨Y(jié)一下就是位段跟結(jié)構(gòu)相比,可以達(dá)到相同效果且可以有效節(jié)省空間,但存在跨平臺(tái)問(wèn)題存在。
Tip
注意,位段機(jī)制跟棧還扯不上關(guān)系,入棧的是數(shù)據(jù)的字節(jié),位段是在這些字節(jié)的內(nèi)部空間上發(fā)揮作用,已經(jīng)細(xì)節(jié)到“位”了,以及之前提到的大小端模式,大小端是連續(xù)字節(jié)數(shù)據(jù)的存放模式,也細(xì)化不到字節(jié)上。
應(yīng)用場(chǎng)景
位段在實(shí)際生活中也有廣泛的應(yīng)用,比如我們網(wǎng)絡(luò)上數(shù)據(jù)包的格式:
這就是我們?cè)诨ヂ?lián)網(wǎng)上向某個(gè)對(duì)象發(fā)送信息的原理,里面最大的問(wèn)題就是這個(gè)包如果直接扔到網(wǎng)上去,就會(huì)像拖拉機(jī)上高速,鐵鐵的堵車(chē)造成網(wǎng)絡(luò)擁擠,我們就會(huì)利用位段機(jī)制進(jìn)行適當(dāng)縮減以減小網(wǎng)絡(luò)的負(fù)擔(dān)。
今天就到這里吧,摸了家人們。
以上就是C語(yǔ)言位段(位域)機(jī)制結(jié)構(gòu)體的特殊實(shí)現(xiàn)及解析的詳細(xì)內(nèi)容,更多關(guān)于C語(yǔ)言位段位域機(jī)制結(jié)構(gòu)體的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C語(yǔ)言進(jìn)階輸入輸出重定向與fopen函數(shù)使用示例詳解
這篇文章主要為大家介紹了C語(yǔ)言進(jìn)階輸入輸出重定向與fopen函數(shù)的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-02-02C++利用MySQL API連接和操作數(shù)據(jù)庫(kù)實(shí)例詳解
這篇文章主要介紹了C++利用MySQL API連接和操作數(shù)據(jù)庫(kù)實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-01-01C 語(yǔ)言關(guān)于聯(lián)合體的相關(guān)知識(shí)
這篇文章主要介紹了C 語(yǔ)言關(guān)于聯(lián)合體的相關(guān)知識(shí),文中講解非常細(xì)致,代碼幫助大家更好的理解學(xué)習(xí),感興趣的朋友可以了解下2020-06-06C++數(shù)據(jù)結(jié)構(gòu)之二叉搜索樹(shù)的實(shí)現(xiàn)詳解
二叉搜索樹(shù)作為一個(gè)經(jīng)典的數(shù)據(jù)結(jié)構(gòu),具有鏈表的快速插入與刪除的特點(diǎn),同時(shí)查詢效率也很優(yōu)秀,所以應(yīng)用十分廣泛。本文將詳細(xì)講講二叉搜索樹(shù)的C++實(shí)現(xiàn),需要的可以參考一下2022-08-08C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單餐飲管理與點(diǎn)餐系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單餐飲管理與點(diǎn)餐系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05C語(yǔ)言編程中對(duì)目錄進(jìn)行基本的打開(kāi)關(guān)閉和讀取操作詳解
這篇文章主要介紹了C語(yǔ)言編程中對(duì)目錄進(jìn)行基本的打開(kāi)關(guān)閉和讀取操作,是C語(yǔ)言入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-09-09