位域允許在結構體中以位為單位劃分成員,極大節省內存,是嵌入式寄存器映射、協議解析、標誌位管理的利器。本文系統講解語法、佈局規則、移植性陷阱與實戰模式。
struct BitFieldStruct {
類型 成員名 : 位寬;
// 例:
unsigned int flag1 : 1; // 1位標誌
unsigned int value : 15; // 15位數值
unsigned int : 0; // 無名位域:強制對齊到下一個整型邊界
unsigned int flag2 : 1;
};
int、signed int、unsigned int(C99允許_Bool)。unsigned int通常32位)。:0)用於填充對齊,不可訪問。int大小(4字節)為單位分配。struct Flags16 {
unsigned char b0 : 1;
unsigned char b1 : 1;
// ... b2~b14
unsigned char b15 : 1;
}; // 共佔2字節(16位),每位獨立可訪問
// 訪問
struct Flags16 f;
f.b0 = 1; f.b3 = 1; // 設置標誌
if (f.b0) { /* ... */ }
typedef struct {
uint8_t mode_flag : 2; // 模式標誌
uint8_t fan_rank : 2; // 風速檔位
uint8_t windsweeper : 1; // 掃風功能
uint8_t reserved : 3; // 保留位
} DeviceStatus; // 精確佔1字節
// 字節與位域互轉
DeviceStatus status;
uint8_t byte = 0x6A; // 0110 1010
status = *(DeviceStatus*)&byte; // 強制類型轉換(需注意嚴格別名規則)
// 更安全:聯合體
typedef union {
DeviceStatus bits;
uint8_t byte;
} StatusConverter;
StatusConverter cvt;
cvt.byte = 0x6A;
// cvt.bits.mode_flag == 2 (10b)
// cvt.bits.fan_rank == 2 (10b)
// cvt.bits.windsweeper == 0
| 陷阱 | 說明 | 對策 |
|---|---|---|
| 位域分配順序 | C標準未規定低位在前還是高位在前 | 僅用於本地內存壓縮,禁止用於網絡協議/文件格式直接映射 |
| 跨存儲單元行為 | 位寬超出剩餘位時是否跨界,編譯器實現定義 | 用無名位域:0強制對齊,或改用位運算手動打包 |
| 有符號位域 | int f:1範圍為-1~0(補碼),非0/1 | 標誌位統一用unsigned |
| 取地址操作 | &bitfield_member非法 | 不可對位域成員取址 |
| 數組化 | 不能定義位域數組 | 改用位運算宏/函數 |
0b0101),需用十六進制或宏。&、|、<<、>>進行讀寫。unsigned類型。:0控制對齊邊界。get/set封裝宏/內聯函數,屏蔽位運算細節。位域是C語言「以空間換時間、以位操作換邏輯清晰度」的特色工具,用好它需敬畏其實現定義特性,在嵌入式領域發揮最大價值。