中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C言語位域

發布時間:2020-07-04 19:21:50 來源:網絡 閱讀:372 作者:yuw2016 欄目:網絡安全

有些數據在存儲時并不需求占用一個完好的字節,只需求占用一個或幾個二進制位即可。例如開關只要通電和斷電兩種形態,用 0 和 1 表現足以,也就是用一個二進位。恰是基于這種思索,C言語又供給了一種叫做位域的數據構造。
在構造體界說時,我們可以指定某個成員變量所占用的二進制位數(Bit),這就是位域。請看下面的例子:

			struct bs{ unsigned m; unsigned n: 4; unsigned char ch: 6; }

:前面的數字用來限制成員變量占用的位數。成員 m 沒無限制,依據數據類型即可推算出它占用 4 個字節(Byte)的內存。成員 n、ch 被:前面的數字限制,不克不及再依據數據類型盤算長度,它們辨別占用 4、6 位(Bit)的內存。
n、ch 的取值規模十分無限,數據略微大些就會發作溢出,請看下面的例子:

			#include <stdio.h> int main(){ struct bs{ unsigned m; unsigned n: 4; unsigned char ch: 6; } a = { 0xad, 0xE, '$'}; //第一次輸入 printf("%#x, %#x, %c\n", a.m, a.n, a.ch); //更改值后再次輸入 a.m = 0xb8901c; a.n = 0x2d; a.ch = 'z'; printf("%#x, %#x, %c\n", a.m, a.n, a.ch); return 0; }

運轉后果:
0xad, 0xe, $
0xb8901c, 0xd, :
關于 n 和 ch,第一次輸入的數據是完好的,第二次輸入的數據是完整的。
第一次輸入時,n、ch 的值辨別是 0xE、0x24('$' 對應的 ASCII 碼為 0x24),換算成二進制是 1110、10 0100,都沒有超越限制的位數,可以正常輸入。
第二次輸入時,n、ch 的值變為 0x2d、0x7a('z' 對應的 ASCII 碼為 0x7a),換算成二進制辨別是 10 1101、111 1010,都超越了限制的位數。超越局部被直接截去,剩下 1101、11 1010,換算成十六進制為 0xd、0x3a(0x3a 對應的字符是 :)。
C言語規范規則,位域的寬度不克不及超越它所依靠的數據類型的長度。淺顯地講,成員變量多是有類型的,這個類型限制了成員變量的最大長度,:前面的數字不克不及超越這個長度。
例如下面的 bs,n 的類型是 unsigned int,長度為 4 個字節,合計 32 位,那么 n 前面的數字就不克不及超越 32;ch 的類型是 unsigned char,長度為 1 個字節,合計 8 位,那么 ch 前面的數字就不克不及超越 8。
我們可以如許以為,位域技巧就是在成員變量所占用的內存當選出一局部位寬來存儲數據。
C言語規范還規則,只要無限的幾種數據類型可以用于位域。在 ANSI C 中,這幾種數據類型是 int、signed int 和 unsigned int(int 默許就是 signed int);到了 C99,_Bool 也被支撐了。

關于C言語規范以及 ANSI C 和 C99 的差別,我們已在VIP教程《C言語的兩套規范》中停止了解說。

但編譯器在詳細完成時都停止了擴大,額定支撐了 char、signed char、unsigned char 以及 enum 類型,所以下面的代碼固然不契合C言語規范,但它仍然可以被編譯器支撐。

位域的存儲

C言語規范并沒有規則位域的詳細存儲方法,分歧的編譯器有分歧的完成,但它們都盡量緊縮存儲空間。
位域的詳細存儲規矩如下:
1) 當相鄰成員的類型相反時,假如它們的位寬之和小于類型的 sizeof 巨細,那么前面的成員緊鄰前一個成員存儲,直到不克不及包容為止;假如它們的位寬之和大于類型的 sizeof 巨細,那么前面的成員將重新的存儲單位開端,其偏移量為類型巨細的整數倍。
以下面的位域 bs 為例:

			#include <stdio.h> int main(){ struct bs{ unsigned m: 6; unsigned n: 12; unsigned p: 4; }; printf("%d\n", sizeof(struct bs)); return 0; }

運轉后果:
4
m、n、p 的類型多是 unsigned int,sizeof 的后果為 4 個字節(Byte),也即 32 個位(Bit)。m、n、p 的位寬之和為 6+12+4 = 22,小于 32,所以它們會挨著存儲,兩頭沒有裂縫。

sizeof(struct bs) 的巨細之所認為 4,而不是 3,是由于要將內存對齊到 4 個字節,以便進步存取效力,這將在《C言語和內存》專題的《C言語內存對齊,進步尋址效力》一節中具體解說。

假如將成員 m 的位寬改為 22,那么輸入后果將會是 8,由于 22+12 = 34,大于 32,n 會重新的地位開端存儲,絕對 m 的偏移量是 sizeof(unsigned int),也即 4 個字節。
假如再將成員 p 的位寬也改為 22,那么輸入后果將會是 12,三個成員都不會挨著存儲。
2) 當相鄰成員的類型分歧時,分歧的編譯器有分歧的完成計劃,GCC 會緊縮存儲,而 VC/VS 不會。
請看下面的位域 bs:

			#include <stdio.h> int main(){ struct bs{ unsigned m: 12; unsigned char ch: 4; unsigned p: 4; }; printf("%d\n", sizeof(struct bs)); return 0; }

在 GCC 下的運轉后果為 4,三個成員挨著存儲;在 VC/VS 下的運轉后果為 12,三個成員依照各自的類型存儲(與不指定位寬時的存儲方法相反)。

m 、ch、p 的長度辨別是 4、1、4 個字節,合計占用 9 個字節內存,為什么在 VC/VS 下的輸入后果倒是 12 呢?這個疑問將在《C言語和內存》專題的《C言語內存對齊,進步尋址效力》一節中為您解開。

3) 假如成員之間交叉著非位域成員,那么不會停止緊縮。例如關于下面的 bs:

			struct bs{ unsigned m: 12; unsigned ch; unsigned p: 4; };

在各個編譯器下 sizeof 的后果多是 12。
經過下面的剖析,我們發現位域成員常常不占用完好的字節,有時分也不處于字節的掃尾地位,因而運用&獲取位域成員的地址是沒有意義的,C言語也制止如許做。地址是字節(Byte)的編號,而不是位(Bit)的編號。

無名位域

位域成員可以沒著名稱,只給出數據類型和位寬,如下所示:

			struct bs{ int m: 12; int : 20; //該位域成員不克不及運用 int n: 4; };

無名位域普通用來作填充或許調劑成員地位。由于沒著名稱,無名位域不克不及運用。
下面的例子中,假如沒有位寬為 20 的無名成員,m、n 將會挨著存儲,sizeof(struct bs) 的后果為 4;有了這 20 位作為填充,m、n 將離開存儲,sizeof(struct bs) 的后果為 8。


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

务川| 彭州市| 石阡县| 武清区| 永州市| 华亭县| 广宗县| 将乐县| 合肥市| 临漳县| 都兰县| 新化县| 尤溪县| 吴旗县| 永安市| 区。| 文成县| SHOW| 即墨市| 温宿县| 乌兰察布市| 石景山区| 金溪县| 清水县| 辽源市| 营山县| 阿克陶县| 萝北县| 邹城市| 千阳县| 盐山县| 囊谦县| 固原市| 县级市| 清远市| 平果县| 连江县| 深泽县| 铜梁县| 偃师市| 斗六市|