位段(或稱「位域」,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)長度的相鄰位域儘量裝入基類型的同一個對象,如果裝得下的話。

參考文獻

編輯
  1. ^ ISO 14882 C++14 standard §9.6.1: "Allocation of bit-fields within a class object is implementation-defined. Alignment of bit-fields is implementation-defined. Bit-fields are packed into some addressable allocation unit. [Note: Bit-fields straddle allocation units on some machines and not on others. Bit-fields are assigned right-to-left on some machines, left-to-right on others. —end note ]"
  2. ^ ISO 14882 C++14 standard §9.6.2
  3. ^ How Endianness Effects Bitfield Packing. [2017-03-15]. (原始內容存檔於2017-05-10). 
  4. ^ [[MSDN]] "Storage and Alignment of Structures" wrote: Adjacent bit fields are packed into the same 1-, 2-, or 4-byte allocation unit if the integral types are the same size and if the next bit field fits into the current allocation unit without crossing the boundary imposed by the common alignment requirements of the bit fields.. [2017-03-15]. (原始內容存檔於2017-03-15).