位域允許指定結構體成員佔用的精確位數,極大減少內存佔用,常用於嵌入式系統、網絡協議解析、硬件寄存器映射。
typedef struct {
unsigned int second : 6; // 0-63,實際 0-59
unsigned int minute : 6; // 0-63,實際 0-59
unsigned int hour : 5; // 0-31,實際 0-23
unsigned int day : 5; // 0-31,實際 1-31
unsigned int month : 4; // 0-15,實際 1-12
unsigned int year : 6; // 0-63,對應 2000-2063
} Time_t;
// sizeof(Time_t) 通常為 4 字節(32 位),而非 6 × 4 = 24 字節
C99 支援指定初始化器,但無構造函數。可通過「靜態內聯函數 + 複合字面量」模擬:
typedef struct {
uint32_t count;
uint8_t buffer[1024];
} Info_t;
// 初始化函數(內聯優化)
static inline void Info_init(Info_t *self) {
self->count = 0;
memset(self->buffer, 0, sizeof(self->buffer));
}
// 使用:複合字面量 + 初始化函數
Info_t info = {0}; // C99 指定初始化或零初始化
Info_init(&info);
// 或一行式(GNU 擴展)
#define INFO_INITIALIZER { .count = 0, .buffer = {0} }
Info_t info2 = INFO_INITIALIZER;
// 現代 C 寫法,清晰且安全
Info_t info = {
.count = 0,
.buffer = {0} // 首元素為 0,其餘自動補 0
};
// 部分初始化
Info_t info3 = { .count = 42 }; // buffer 自動零初始化
結構體最後一個成員可為不定長數組,配合動態分配實現變長結構:
typedef struct {
size_t len;
char data[]; // 柔性數組,不佔用結構體大小
} String_t;
String_t *create_string(const char *src) {
size_t len = strlen(src);
String_t *s = malloc(sizeof(String_t) + len + 1);
if (s) {
s->len = len;
memcpy(s->data, src, len + 1);
}
return s;
}
| 技巧 | 適用場景 | C 標準 | 注意事項 |
|---|---|---|---|
| 位域 | 硬件映射、協議解析、極度受限內存 | C89 | 不可移植、不可取址、簽名/無符號行為差異 |
| 指定初始化器 | 所有結構體初始化 | C99 | 最推薦,可讀性強、順序無關、自動零填充 |
| 柔性數組 | 變長數據、字符串、數據包 | C99 | 需手動 malloc/free,不能作為數組元素 |