位域(Bit-field)允許在結構體中以位為單位聲明成員,多個位域緊湊排列在一個或多個整型存儲單元中。適用於標誌位組合、硬件寄存器映射、網絡協議頭部、極度受限內存環境。
struct BitStruct {
type name1 : width1;
type name2 : width2;
// ...
};
type:只能是 int、signed int、unsigned int(C99 允許 _Bool)。width:位寬,不能超過所依附類型的位寬(如 int 通常 32 位,但單個位域不超過 1 個存儲單元)。struct Status {
unsigned int ready : 1; // 1 位:就緒標誌
unsigned int error : 1; // 1 位:錯誤標誌
unsigned int code : 6; // 6 位:錯誤碼 0-63
// 共 8 位,佔 1 字節
};
:0 強制換行:unsigned int :0; 強制下一位域從新存儲單元開始。struct Demo {
unsigned a : 4;
unsigned : 0; // 強制換行,後 4 位填充廢棄
unsigned b : 4; // 從下一字節第 0 位開始
unsigned c : 4; // 緊接 b 之後
};
// 佈局(假設 8 位/字節,低位優先):
// 字節 0: a(4位) + 填充(4位)
// 字節 1: b(4位) + c(4位)
// sizeof(Demo) == 2
struct K {
int a : 1;
int : 2; // 2 位填充,不可訪問
int b : 3;
int c : 2;
};
// 用於保留位、對齊硬件寄存器保留位
struct BS {
unsigned a : 1;
unsigned b : 3;
unsigned c : 4;
} bit, *pbit = &bit;
bit.a = 1; // 僅 0/1
bit.b = 7; // 0-7
bit.c = 15; // 0-15
printf("%d,%d,%d\n", bit.a, bit.b, bit.c); // 1,7,15
// 指針操作
pbit->a = 0;
pbit->b &= 3; // 7 & 3 = 3
pbit->c |= 1; // 15 | 1 = 15
printf("%d,%d,%d\n", pbit->a, pbit->b, pbit->c); // 0,3,15
| 限制 | 說明 |
|---|---|
| 不能取地址 | &bit.a 編譯錯誤,位域無地址 |
| 不能跨存儲單元 | 位寬 > 單元位寬 編譯錯誤 |
| 有符號位域陷阱 | int x:3 範圍 -4..3,非 0..7。推薦統一用 unsigned |
| 佈局不可移植 | 位域分配順序、填充規則由 ABI 決定,勿用於跨平台數據交換 |
| 數組不可行 | 不能聲明位域數組 int bits[8]:1 |
| 效能權衡 | 讀寫位域需指令級掩碼操作,頻繁訪問可能比手動掩碼更慢 |
struct Reg { unsigned EN:1; unsigned MODE:2; unsigned :5; unsigned DATA:8; };struct { unsigned FIN:1; SYN:1; RST:1; PSH:1; ACK:1; URG:1; :2; WINDOW:16; }。位域是 C 語言以聲明式方式實現位級數據佈局的機制。理解「存儲單元不跨越、:0 強制換行、有符號陷阱、佈局不可移植」四大鐵律,能在嵌入式寄存器操作、協議解析等場景少踩無數坑。但記住:通用數據交換請用手動掩碼+移位,而非位域。