C 位元欄位
除了結構或等位成員的宣告子之外,結構宣告子也可以指定為位元數目 (稱為「位元欄位」)。其長度是依冒號從欄位名稱的宣告子所設定。 位元欄位會以整數類型解譯。
語法
struct-declarator
:
declarator
type-specifier
declarator
opt :
constant-expression
constant-expression
會以位元指定欄位的寬度。 declarator
的 type-specifier
必須是 unsigned int
、signed int
或 int
,而 constant-expression
必須是非負整數值。 若該值是零,宣告沒有 declarator
。 不允許位元欄位陣列、位元欄位指標與傳回位元欄位的函式。 選擇性的 declarator
會為位元欄位命名。 位元欄位只能宣告為結構的一部分。 address-of 運算子 (&
) 無法套用至位元欄位元件。
無法參考未具名位元欄位,而且其內容在執行階段無法預測。 它們可以當作「虛設」欄位使用,以用於對齊用途。 未具名的位元欄位寬度指定為 0 時,可保證 struct-declaration-list 中跟隨在其後的成員儲存區是以 int
界限開始。
位元欄位中的位元數必須小於或等於基礎類型的大小。 例如,這兩個陳述式不合法:
short a:17; /* Illegal! */
int long y:33; /* Illegal! */
此範例定義名為 screen
之結構的二維陣列。
struct
{
unsigned short icon : 8;
unsigned short color : 4;
unsigned short underline : 1;
unsigned short blink : 1;
} screen[25][80];
陣列包含 2,000 個元素。 每個元素都是個別的結構,其中包含四個位元欄位成員:icon
、color
、underline
與 blink
。 每個結構的大小都是 2 個位元組。
位元欄位具有與整數類型相同的語意。 在運算式中使用位元欄位的方式與使用相同基底類型的變數完全相同。 位元欄位中有多少位元並不重要。
Microsoft 特定的
定義為 int
的位元欄位會被視為 signed
。 Microsoft 的 ANSI C 標準延伸模組允許對位元欄位使用 char
和 long
類型 (signed
和 unsigned
)。 具有基底類型 long
、short
或 char
(signed
或 unsigned
) 的未具名位元欄位會強制對齊基底類型適用的界限。
位元欄位是在整數內依最小顯著性到最高有效位元的順序配置。 在下列程式碼中
struct mybitfields
{
unsigned short a : 4;
unsigned short b : 5;
unsigned short c : 7;
} test;
int main( void )
{
test.a = 2;
test.b = 31;
test.c = 0;
return 0;
}
test
的位元排列如下:
00000001 11110010
cccccccb bbbbaaaa
因為 8086 系列處理器會先儲存整數值的低位元組,再儲存高位元組,整數 0x01F2
將儲存到實體記憶體作為 0xF2
,後面接著 0x01
。
ISO C99 標準可讓實作選擇位元欄位是否可能跨越兩個儲存體執行個體。 請考慮此結構,其會儲存總計 64 位元的位元欄位:
struct
{
unsigned int first : 9;
unsigned int second : 7;
unsigned int may_straddle : 30;
unsigned int last : 18;
} tricky_bits;
標準 C 實作可以將這些位元欄位封裝成兩個 32 位元的整數。 它可能會將 tricky_bits.may_straddle
儲存為一個 32 位元整數中的 16 位元,並在下一個 32 位元整數中儲存 14 位元。 Windows ABI 慣例會將位元欄位封裝成單一儲存整數,而且不會跨越儲存單位。 Microsoft 編譯器會將儲存上述範例中的每個位元欄位,使其完全符合單一 32 位元整數。 在此情況下,first
和 second
會儲存在一個整數中,may_straddle
會儲存在第二個整數中,而 last
則儲存在第三個整數中。 sizeof
運算子會在 tricky_bits
的執行個體上傳回 12
。 如需詳細資訊,請參閱結構成員的填補和對齊。
END Microsoft 特定的