位元欄(或稱「位域」,Bit field)為一種數據結構,可以把數據以位元的形式緊湊的儲存,並允許程式設計師對此結構的位元進行操作。這種數據結構的好處:

  • 可以使數據單元節省儲存空間,當程式需要成千上萬個數據單元時,這種方法就顯得尤為重要。
  • 位元欄可以很方便的訪問一個整數值的部分內容從而可以簡化程式原始碼。

而位域這種數據結構的缺點在於,其主記憶體分配與主記憶體對齊的實現方式依賴於具體的機器和系統,在不同的平台可能有不同的結果,這導致了位元欄在本質上是不可移植的。[1]

簡介

在C語言中,位元欄的聲明和結構(struct)類似,但它的成員是一個或多個位元的欄位,這些不同長度的欄位實際儲存在一個或多個整型變數中。在聲明時,位元欄成員必須是整形或列舉類型(通常是無符號類型),且在成員名的後面是一個冒號和一個整數,整數規定了成員所佔用的位元數。位域不能是靜態型別。不能使用&對位域做取地址運算,因此不存在位域的指標,編譯器通常不支援位域的參照(reference)。以下程式則展示了一個位元欄的聲明:

struct CHAR 
{
    unsigned int ch   : 8;    //8位
    unsigned int font : 6;    //6位
    unsigned int size : 18;   //18位
};
struct CHAR ch1;

以下程式展示了一個結構體的聲明:

struct CHAR2 
{
    unsigned char ch;    //8位
    unsigned char font;  //8位
    unsigned int  size;  //32位
};
struct CHAR2 ch2;

第一個聲明取自一段文字格式化程式,應用了位元欄聲明。它可以處理256個不同的字元(8位元),64種不同字型(6位元),以及最多262,144個單位的長度(18位元)。這樣,在ch1這個欄位對象中,一共才佔據了32位元的空間。而第二個程式利用結構體進行聲明,可以看出,處理相同的數據,CHAR2類型佔用了48位元空間,如果考慮邊界對齊並把要求最嚴格的int類型最先聲明進行最佳化,那麼CHAR2類型則要佔據64位元的空間。

無名位域

如果位域的定義沒有給出識別碼名字,那麼這是無名位域,無法被初始化。[2]無名位域用於填充(padding)主記憶體佈局。只有無名位域的位元數可以為0。這種佔0位元的無名位域,用於強迫下一個位域在主記憶體分配邊界對齊。

實現

通常在大端序系統(如PowerPC),安排位域從最重要位元組(most-significant byte)到最不重要位元組(least-significant byte),在一個位元組內部從最重要位(most-significant bit)到最不重要位(least-significant bit);而在小端序系統(如x86),安排位域從最不重要位元組(least-significant byte)到最重要位元組(most-significant byte),在一個位元組內部從最不重要位(least-significant bit)到最重要位(most-significant bit)。[3]共同遵從的原則是主記憶體位元組地址從低到高,主記憶體內部的位元編號英語bit numbering從低到高。

Microsoft Visual C++實現

在一個整數(integer)內的位域從最不重要位(least-significant)向最重要位(most-significant)依次分配。

相鄰的兩個位域如果基本類型(underlying type)的長度相同,在後的位域適合當前主記憶體單位配置且沒有跨主記憶體分配邊界,那麼這兩個位域分配到同一個(1、2或4位元組的)單位配置。[4] 這可以通俗理解為:具有相同的基本類型(underlying type)長度的相鄰位域儘量裝入基本類型的同一個對象,如果裝得下的話。

參考文獻

Wikiwand in your browser!

Seamless Wikipedia browsing. On steroids.

Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.

Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.