看runtime源碼時,看到以下聲明變量的,變量後分號前加冒號和數字": 數字"即爲位域操做。html
uintptr_t indexed : 1;
1個字節包含8位,有些變量保存的數據不須要佔用這麼長的空間(好比bool類型,只有兩個狀態true和false, 1位就能夠搞定,剩下的7位就浪費了),這就催生了「位域」結構,位域將1個字節劃分紅不一樣的區域,每一個區域都有個位域名(能夠理解爲變量名,上邊的代碼中位域名爲indexed),程序員能夠代碼經過位域名訪問其中的數據。程序員
一. 聲明測試
類型說明符 位域名:位域長度;
位域結構體,我理解是一種特殊的結構體,其成員變量都是位域,聲明以下ui
struct 位域結構名 {
類型說明符 位域名:位域長度;
類型說明符 位域名:位域長度;
類型說明符 位域名:位域長度;
...
類型說明符 位域名:位域長度;
};
二. 基本原則spa
1. 位域變量的長度不能大於其類型的長度(sizeof(類型) * 8)code
變量char has_assoc的類型位char 1字節 8位,小於定義的10,因此編譯器警告htm
2. 不能用於位域字段的操做:取地址操做符&,取偏移量操做blog
位域是若干位空間,是沒有地址的內存
3. 位域能夠是無名位域,無名位域只能用做填充或調整位置,不能使用。以下圖結構體S007的最後一個變量就是無名位域,沒法使用get
4. 位域字段不能聲明爲類的靜態成員
5. 位域結構體的大小必須是其最長基本類型大小的整數倍(sizeof(類型) * 8)
三. 內存分配規則
1. 判斷大小端,以我本身的機子爲例,不一樣環境下有可能不一樣
定義聯合體U007和位域結構體S007,將U007實例u7的number賦值31,二進制爲 | 0000 0000 | 0000 0000 | 0000 0000 | 0001 1111 |,根據存儲原則,數值都是從高地址往低地址讀,所以位域結構體S007中的位域變量是從低地址開始分配內存的,即
2. 位域變量類型相同
位域變量長度之和小於[sizeof(變量類型)*8], 則後面的位域字段將緊鄰前一個字段存儲, 直到不能容納爲止
位域變量長度之和大於[sizeof(變量類型)*8], 則後面的位域字段將從下一個存儲單元的起始地址處開始存放(其偏移量剛好爲sizeof(變量類型)的整數倍)
位域結構體S007的3個成員變量都是unfigned short類型,sizeof(unfigned short)*8 = 16位,
a0佔1位,從起始地址分配1位;
a1佔9位,a0+a1=10位,小於16位(sizeof(unfigned short)*8),所以a1在a0後連續分配9位;
a2佔15位,(a0 + a1) + a2 = 25位,大於16位,所以跳過6位,在S007起始地址偏移量爲16位的地方,給a2分配15位。
再次提醒:小端是分配內存地址時從低地址開始,可是變量的數值是從高地址往低地址讀
3. 位域變量類型不一樣時,各個編譯器的具體實現有差別,VC6採起不壓縮方式,GCC和Dev-C++都採用壓縮方式,如下是我本身機子的處理方式
位域結構體S007的前2個成員變量unfigned char類型(sizeof(unfigned char)*8 = 8位),後一個成員變量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後連續分配3位;
c佔15位,(a + b) + c = 20位,大於16位(sizeof(unfigned short)*8,c的類型是unfigned short),所以跳過11位,在S007起始地址偏移量爲16位的地方,給c分配15位。
有上圖能夠看出,在個人機子上,若是位域變量的類型不一樣,仍會進行內存壓縮(若是須要跳位,判斷哪一個位域變量,就用該變量的類型進行偏移量對齊判斷)
4. 若是位域變量之間穿插着非位域變量, 則不進行壓縮
非位域變量也能夠理解爲特殊的位域變量,只不過佔的位數是變量長度,即 類型 位域名 : sizeof(類型)*8
根據規則3,則沒法進行內存壓縮
位域結構體S007的第2個成員變量char tmp;是非位域變量,轉成位域變量爲 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. 上邊舉的例子中參數都是unsigned標識的,若是帶上符號位會是什麼狀況呢?
關於帶符號基本類型變量在內存中存儲方式,請看這裏http://www.cnblogs.com/xieyajie/p/8125214.html
位域結構體S008定義了2個帶符號位域變量,a0佔2位,a1佔3位
a0是帶符號short類型,內存中保存的是補碼11,首位符號位爲1,負數,推出源碼爲11,轉爲十進制爲-1;
a1是帶符號short類型,內存中保存的是補碼001,首位符號位爲0,正數,源碼爲001,轉爲十進制爲1。
若是a0只佔1位會怎麼樣?從測試結果能夠看出,這1位幾十符號位,也是數值位