日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

位域操作

發(fā)布時(shí)間:2023/12/10 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 位域操作 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

看runtime源碼時(shí),看到如下聲明變量的,變量后分號(hào)前加冒號(hào)和數(shù)字": 數(shù)字"即為位域操作。

uintptr_t indexed : 1;

?

1個(gè)字節(jié)包含8位,有些變量保存的數(shù)據(jù)不需要占用這么長(zhǎng)的空間(比如bool類型,只有兩個(gè)狀態(tài)true和false, 1位就可以搞定,剩下的7位就浪費(fèi)了),這就催生了“位域”結(jié)構(gòu),位域?qū)?個(gè)字節(jié)劃分成不同的區(qū)域,每個(gè)區(qū)域都有個(gè)位域名(可以理解為變量名,上邊的代碼中位域名為indexed),程序員可以代碼通過位域名訪問其中的數(shù)據(jù)。

?

一. 聲明

類型說(shuō)明符 位域名:位域長(zhǎng)度;

?

位域結(jié)構(gòu)體,我理解是一種特殊的結(jié)構(gòu)體,其成員變量都是位域,聲明如下

?

struct 位域結(jié)構(gòu)名 {
  類型說(shuō)明符 位域名:位域長(zhǎng)度;   類型說(shuō)明符 位域名:位域長(zhǎng)度;   類型說(shuō)明符 位域名:位域長(zhǎng)度;
  ...   類型說(shuō)明符 位域名:位域長(zhǎng)度; };

??

二. 基本原則

1. 位域變量的長(zhǎng)度不能大于其類型的長(zhǎng)度(sizeof(類型) * 8)

變量char has_assoc的類型位char 1字節(jié) 8位,小于定義的10,所以編譯器警告

?

2.??不能用于位域字段的操作:取地址操作符&,取偏移量操作

位域是若干位空間,是沒有地址的

?

?

3.?位域可以是無(wú)名位域,無(wú)名位域只能用作填充或調(diào)整位置,不能使用。如下圖結(jié)構(gòu)體S007的最后一個(gè)變量就是無(wú)名位域,無(wú)法使用

?

4.?位域字段不能聲明為類的靜態(tài)成員

?

5.?位域結(jié)構(gòu)體的大小必須是其最長(zhǎng)基本類型大小的整數(shù)倍(sizeof(類型) * 8)

?

三. 內(nèi)存分配規(guī)則

1. 判斷大小端,以我自己的機(jī)子為例,不同環(huán)境下有可能不同

?

定義聯(lián)合體U007和位域結(jié)構(gòu)體S007,將U007實(shí)例u7的number賦值31,二進(jìn)制為 | 0000 0000 | 0000 0000 | 0000 0000 | 0001 1111 |,根據(jù)存儲(chǔ)原則,數(shù)值都是從高地址往低地址讀,因此位域結(jié)構(gòu)體S007中的位域變量是從低地址開始分配內(nèi)存的,即

?

2. 位域變量類型相同

位域變量長(zhǎng)度之和小于[sizeof(變量類型)*8], 則后面的位域字段將緊鄰前一個(gè)字段存儲(chǔ), 直到不能容納為止

位域變量長(zhǎng)度之和大于[sizeof(變量類型)*8],?則后面的位域字段將從下一個(gè)存儲(chǔ)單元的起始地址處開始存放(其偏移量恰好為sizeof(變量類型)的整數(shù)倍)

?

位域結(jié)構(gòu)體S007的3個(gè)成員變量都是unfigned short類型,sizeof(unfigned short)*8 = 16位,

a0占1位,從起始地址分配1位;

a1占9位,a0+a1=10位,小于16位(sizeof(unfigned short)*8),因此a1在a0后連續(xù)分配9位;

a2占15位,(a0 + a1) + a2 = 25位,大于16位,因此跳過6位,在S007起始地址偏移量為16位的地方,給a2分配15位。

再次提醒:小端是分配內(nèi)存地址時(shí)從低地址開始,但是變量的數(shù)值是從高地址往低地址讀

?

3. 位域變量類型不同時(shí),各個(gè)編譯器的具體實(shí)現(xiàn)有差異,VC6采取不壓縮方式,GCC和Dev-C++都采用壓縮方式,以下是我自己機(jī)子的處理方式

?

位域結(jié)構(gòu)體S007的前2個(gè)成員變量unfigned char類型(sizeof(unfigned char)*8 = 8位),后一個(gè)成員變量unfigned short(sizeof(unfigned short)*8 = 16位)

?

a占2位,從起始地址分配2位;

b占3位,a+b=5位,小于8位(sizeof(unfigned char)*8,b的類型是unfigned char),因此b在a后連續(xù)分配3位;

c占15位,(a + b) + c = 20位,大于16位(sizeof(unfigned short)*8,c的類型是unfigned short),因此跳過11位,在S007起始地址偏移量為16位的地方,給c分配15位。

?

有上圖可以看出,在我的機(jī)子上,如果位域變量的類型不同,仍會(huì)進(jìn)行內(nèi)存壓縮(如果需要跳位,判斷哪個(gè)位域變量,就用該變量的類型進(jìn)行偏移量對(duì)齊判斷)

?

?4.?如果位域變量之間穿插著非位域變量, 則不進(jìn)行壓縮

非位域變量也可以理解為特殊的位域變量,只不過占的位數(shù)是變量長(zhǎng)度,即 類型 位域名 : sizeof(類型)*8

根據(jù)規(guī)則3,則無(wú)法進(jìn)行內(nèi)存壓縮

?

位域結(jié)構(gòu)體S007的第2個(gè)成員變量char tmp;是非位域變量,轉(zhuǎn)成位域變量為 char tmp:8;

?

a占2位,從起始地址分配2位;

tmp占8位,a+tmp=10位,大于8位(sizeof(char)*8,tmp的類型是char),因此跳過6位,在S007起始地址偏移量為8位的地方,給tmp分配8位;

b占3位,在tmp后給b分配3位。

?

?

5. 上邊舉的例子中參數(shù)都是unsigned標(biāo)識(shí)的,如果帶上符號(hào)位會(huì)是什么情況呢?

關(guān)于帶符號(hào)基本類型變量在內(nèi)存中存儲(chǔ)方式,請(qǐng)看這里http://www.cnblogs.com/xieyajie/p/8125214.html

?

位域結(jié)構(gòu)體S008定義了2個(gè)帶符號(hào)位域變量,a0占2位,a1占3位

a0是帶符號(hào)short類型,內(nèi)存中保存的是補(bǔ)碼11,首位符號(hào)位為1,負(fù)數(shù),推出源碼為11,轉(zhuǎn)為十進(jìn)制為-1;

a1是帶符號(hào)short類型,內(nèi)存中保存的是補(bǔ)碼001,首位符號(hào)位為0,正數(shù),源碼為001,轉(zhuǎn)為十進(jìn)制為1。

?

如果a0只占1位會(huì)怎么樣?從測(cè)試結(jié)果可以看出,這1位幾十符號(hào)位,也是數(shù)值位

轉(zhuǎn)載于:https://www.cnblogs.com/xieyajie/p/8110224.html

總結(jié)

以上是生活随笔為你收集整理的位域操作的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。