C语言位段使用详解
博客原文:https://blog.csdn.net/u013427969/article/details/53015872
什么是位段
在前面各章中, 我們已經討論過字節概念了。在大多數的計算機系統中, 一個字節是由八個更小的, 稱作為位的單位組成的。位是比字節更小的單位。位只有兩個值,?1?或?0?。因此, 存儲在計算機存儲器中的一個字節可以看成由八個二進制數字形成的串。
例如, 一個存放值 36 的字節是八個二進制數字的串: 可以表示成 00100100。 存入值24 的字節可以表示成 00010100。
有時, 我們希望不僅對字節進行操作, 也要能對位進行操作。例如, 用布爾真或假條件表示的標志, 在計算機中可用位來表示。
但是, 說明一個用作標志的普通變量至少要用一個字節---8 位, 而在某些計算機系統中則可能是 16 位。 如果我們想在一個很大的表中存儲很多標志, 那么 "被浪費" 的內存空間是很可觀的。在 C 語言中, 一種方法是用叫做位段的構造類型來定義一個壓縮信息的結構。
什么是位段呢? 位段是 C 語言特有的數據結構, 它允許我們定義一個由位組成的段, 并可為它賦以一個名字。
返回頁首
2.位段的用法
我們已經了解什么是位段了, 現在我們繼續討論位段的使用方法。
先看一個例子: 我們需要用到五個變量。 假定, 其中三個用作標志, 稱為 f1, f2 和 f3。
第四個稱為 type, 取值范圍為 1 至 12。 最后一個變量稱為 index, 值的范圍為 0 至 500。
通常, 我們用下面的語句來說明這些變量:?
char f1,f2,f3;
unsigned int type;
unsigned int index;
但是, 實際上標志 f1, f2, f3 分別只需要 1 位。變量 type 只需要 4 位, 而變量 index 只需要 9 位。 總共是 16位 ---- 2 個字節。我們用兩個字節就夠了。
我們可這樣來做:?
struct packed_struct
{
??? unsigned int f1 :1;?
??? unsigned int f2 :1;?
??? unsigned int f3 :1;?
??? unsigned int type :4;
??? unsigned int index :9;
};
該例中, 我們定義了一個結構 packed_struct。該結構定義了五個成員。第一個成員叫做 f1, 是 unsigned int 類型的。緊跟在該成員名之后的 :1 規定了它以 1 位存放。類似地, 標志 f2 和 f3 被定義為長度只有 1 位的。定義成員 type 占有 4 位。定義成員 index 占有 9 位。C 編譯器自動地把上面的位段定義壓縮在一起。位段的劃分如圖所示。packed_struct 總共使用了 16 位。
這種方法的好處是, 定義成 packed_struct 類型的變量的位段, 可以如引用一般的結構成員一樣方便地引用。同時, 使用了更少的內存單元數。
我們已經定義了一個稱作為 packed_struct 的包含著位段的結構。現在, 我們象下面那樣定義一個稱作為 packet_data 的變量: struct packed_struct packed_data; 于是, 我們就可以用簡單的語句, 把 packed_data 的 type 位段設置為 7:?
packed_data.type = 7;?類似地, 我們可以用下面的語句把這個位段的值設為 n:?
packed_data.type = n;?我們不必擔心 n 的值太長, 以致不能放入 type 位段中, C 編譯器會自動地僅取出 n 的低四位, 把它賦值給 packed_data.type。取出位段的值也自動地處理的, 因此語句 n = packed_data.type; 將從 packed_data 中取出 type 位段, 并把它的值賦給 n。
在一般的表達式中可以使用位段, 此時, 位段自動地轉換成整數。因此, 表達式?
i = packed_data.index/5+1;?是完全有效的。
在包含位段的結構中, 也可以包括 "通常的" 數據類型。因此, 如果我們想定義一個結構, 它包含一個 int, 一個 char, 和二個 1 位的標志, 那么, 下面的定義是有效的:?
struct table_entry
{
??? int???? count ;
??? char???? c;
??? unsigned int f1 :1;
??? unsigned int f2 :1;
};
當位段出現在結構定義中時, 它們就被壓縮成字。如果某個位段無法放入一個字中, 那么該字的剩余部分跳過不用, 該位段被放入下一個字中。
使用位段時, 必須注意下列事項:
- 在某些機器上, 位段總是作為 unsigned 處理, 而不管它們是否被說明成 unsigned 的。
- 大多數C 編譯器都不支持超過一個字長的位段。
- 位段不可標明維數; 即, 不能說明位段數組, 例如 flag:l[2]。
- 最后, 不可以取位段地址。原因是, 在這種情況不, 顯然沒有稱作為 "位段指針" 類型的變量。
這里, 我們再深入討論一下位段。如果使用下面的結構定義:
struct bits
{
??? unsigned int f1:1;
??? int???? word;
??? unsigned int f3:1;
};
那么, 位段是怎樣壓縮的呢? 由于成員 word 出現于其間, 故 f1, f3 不會壓縮在同一個字內。C 編譯器不會重新安排位段定義來試圖優化存儲空間。
可以指定無名位段, 使得一個字中的某些位被 "跳過"。因此, 定義:
struct x_entry
{
??? unsigned int type :4;
??? unsigned int :3;
??? unsigned int count :9;
};
將定義一個結構 x_entry, 它包含兩個位段變量 type 和 count, 而無名位段規定了 type 和 count 間隔三位。
總結
- 上一篇: node2vec 图向量
- 下一篇: 分享一个大神的教程