位域

先來看看位域的概念:

位域是指信息在存儲時,並不需要佔用一個完整的字節, 而只需佔幾個或一個二進制位。例如在存放一個開關量時,只有0和1 兩種狀態, 用一位二進位即可。爲了節省存儲空間,並使處理簡便,C語言又提供了一種數據結構,稱爲“位域”或“位段”。所謂“位域”是把一個字節中的二進位劃分爲幾 個不同的區域, 並說明每個區域的位數。每個域有一個域名,允許在程序中按域名進行操作。 這樣就可以把幾個不同的對象用一個字節的二進制位域來表示。

 

struct bs

  {int a:8;int b:2;int c:6;}data;

  說明data爲bs變量,共佔兩個字節。其中位域a佔8位,位域b佔2位,位域c佔6位。

 

對於位域的定義尚有以下幾點說明:

  1. 一個位域必須存儲在同一個字節中,不能跨兩個字節。如一個字節所剩空間不夠存放另一位域時,應從下一單元起存放該位域。也可以有意使某位域從下一單元開始。例如:

  struct bs

  {unsigned a:4unsigned :0 /*空域*/unsigned b:4 /*從下一單元開始存放*/unsigned c:4}

  在這個位域定義中,a佔第一字節的4位,後4位填0表示不使用,b從第二字節開始,佔用4位,c佔用4位。

  2. 位域的長度不能大於指定類型固有長度,比如說int的位域長度不能超過32,bool的位域長度不能超過8。

  3. 位域可以無位域名,這時它只用來作填充或調整位置。無名的位域是不能使用的。例如:

  struct k

  {int a:1int :2 /*該2位不能使用*/int b:3int c:2};

  從以上分析可以看出,位域在本質上就是一種結構類型, 不過其成員是按二進位分配的。

 

再來看看c#,以本人的應用只知道其在枚舉上的使用。

是通過特性[Flags]來定義一個枚舉作爲位域(即一組標誌)處理,來看看例子。

[Flags] 
enum Styles{ 
ShowBorder = 1,         //是否顯示邊框
ShowCaption = 2,        //是否顯示標題
ShowToolbox = 4         //是否顯示工具箱

  這樣我們就可以用"或"運算符組合多個狀態,例如

myControl.Style = Styles.ShowBorder | Styles.ShowCaption; 
 
  這時myControl.Style枚舉的值將變成 1+2=3,它的ToString()將變成"Styles.ShowBorder , Styles.ShowCaption"
  這裏我們可以解釋爲什麼第三個值ShowToolbox可以爲4,5..而不能爲3。也就是說它的值不應該是前幾項值的複合值。有一個比較簡單的方法就是用2的n次方來依次爲每一項賦值,例如 1,2,4,8,16,32,64.....

  現在舉個常見的Flags應用例子。例如一個簡單的權限系統,有"Admin"和"User"兩種角色,我們可以在表中放一個varchar()字段,以文本形式存放權限字"Admin,User"。但是用Flags型枚舉的話,我們就可以直接將 Roles.Admin | Roles.User 的值放在一個int字段裏。

  以下是關於枚舉的一些常見操作:
  將枚舉的值變回枚舉對象:
  Styles style = (Styles) Enum.Parse(typeof(Styles), 4 );    // -> style = Styles.Toolbox;
  檢查枚舉是否包含某個元素:
  bool hasFlag = ((style & Styles.ShowBorder) != 0);

  其實我們還會碰到一種情況,就是需要從組合狀態中去掉一個元素。用"^"運算符可以做到:

  Styles style = Styles.ShowBorder | Styles.ShowCaption; 
  style = style ^ Styles.ShowBorder; 

 

發佈了45 篇原創文章 · 獲贊 6 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章