首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 語言結構體進階技巧:位域與構造函數式初始化

     編輯:關於C語言

技巧一:位域節省內存

位域允許指定結構體成員佔用的精確位數,極大減少內存佔用,常用於嵌入式系統、網絡協議解析、硬件寄存器映射。

時間結構體示例


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 字節

位域關鍵規則

  • 類型必須為整型(`int`、`unsigned int`、`signed int`、`_Bool`)
  • 位域不佔用完整字節時,編譯器嘗試壓緊排列
  • 跨字節邊界時行為為實現定義(通常自動換行)
  • 不能取位域地址(`&time.second` 非法)
  • 無名位域 `: 0` 用於強制對齊到下一個字節邊界

技巧二:構造函數式初始化(C++ 風格在 C 中模擬)

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;

C99 指定初始化器(推薦)


// 現代 C 寫法,清晰且安全
Info_t info = {
    .count = 0,
    .buffer = {0}  // 首元素為 0,其餘自動補 0
};

// 部分初始化
Info_t info3 = { .count = 42 };  // buffer 自動零初始化

技巧三:柔性數組成員(C99)

結構體最後一個成員可為不定長數組,配合動態分配實現變長結構:


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,不能作為數組元素
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved