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

C語言進階:結構體、聯合、位操作、位域與枚舉全景解析

     編輯:C 語言入門

1. 結構體—— 組合異構數據的基石

1.1 定義與變量聲明

struct 關鍵字定義新類型,成員可為任意類型。四種等價定義方式:

// (1) 分離標記與變量\
struct card { char *face; char *suit; };\
struct card aCard, deck[52], *cardPtr;\
\
// (2) 合併聲明\
struct card { char *face; char *suit; } aCard, deck[52], *cardPtr;\
\
// (3) 匿名結構,僅能在此處定義變量\
struct { char *face; char *suit; } aCard, deck[52], *cardPtr;\
\
// (4) typedef 別名,最推薦\
typedef struct { char *face; char *suit; } Card;\
Card aCard, deck[52], *cardPtr;

1.2 內存對齊與「洞」

編譯器為滿足硬件訪問對齊要求(如 4 字節邊界),會在成員間插入填充字節。示例:

struct E { char c; int i; } e1, e2;

在 2 字節字長機器上,c 佔 1 字節,緊接 1 字節填充,i 從地址 2 開始。結構體不可直接用 == 比較,因填充字節值不確定。

結構體內存佈局示意

1.3 初始化、訪問與傳參

  • 初始化:struct card aCard = {"Three", "Hearts"};,少於成員數時剩餘自動置 0/NULL。
  • 訪問:aCard.suit (.)、`cardPtr->suit` (->),後者等價於 (*cardPtr).suit。
  • 函數傳參:值傳遞拷貝整個結構,指針傳遞(const Card*)效率高且可防修改,推薦指針。

1.4 實戰:洗牌發牌程序

代碼亮點:const char* 成員防止字面量被修改;函數參數精心設計 Card* const(指針常量)、const Card* const(指向常量的常量指針),體現最小權限原則。

發牌程序運行結果

2. 聯合—— 同一內存的多重解釋

2.1 定義與特性

union number { int x; double y; };
  • 所有成員共享同一塊內存,大小等於最大成員大小。
  • 僅能用第一個成員類型的值初始化;寫入一個成員、讀取另一個成員可實現類型雙關(如判斷大小端)。
  • 可移植性依賴於系統對齊規則。

2.2 進階用法

  1. 增強可讀性:矩陣同時支持 m._matrix.f[2][2] 整體操作與 m._matrix._f11 單元訪問。
  2. 類型雙關判斷大小端:
union { unsigned int i; char c; } test;\
test.i = 2;\
return test.c != 2;  // 小端機器返回真

3. 位操作—— 底層數據的精準手術刀

3.1 六大運算符

運算符功能示例
&按位與掩碼提取位
|按位或置位
^按位異或翻轉位、無臨時變量交換
~按位取反掩碼取反
<<左移乘 2ⁿ、構建掩碼
>>右移除 2ⁿ、有符號數實現定義

3.2 例:無符號整數二進制輸出

void displayBits(unsigned value) {\
    unsigned mask = 1u << 31;\
    for (int c = 1; c <= 32; ++c) {\
        putchar(value & mask ? '1' : '0');\
        value <<= 1;\
        if (c % 4 == 0) putchar(' ');\
    }\
    putchar('\\n');\
}

二進制輸出效果

4. 位域—— 以位為單位的內存精細管理

4.1 聲明語法

struct bitCard {\
    unsigned face : 4;  // 4位存花色 0-12\
    unsigned suit : 2;  // 2位存花色 0-3\
    unsigned color: 1;  // 1位存顏色 0/1\
};

4.2 特殊用法

  • 無名填充:unsigned : 19; 跳過 19 位,對齊下一存儲單元。
  • 零寬強制對齊:unsigned : 0; 強制下一位域從新存儲單元開始。

4.3 優缺點權衡

優點缺點
極致節省內存無法取地址(&)、無法構成數組
硬件寄存器映射天然契合編譯器生成額外取值/設置指令,執行較慢

典型的空間換時間權衡。

4.4 實戰:52張牌位域版

位域發牌結果

5. 枚舉—— 語義化的整數常量集合

5.1 聲明與賦值規則

enum months { JAN=1, FEB, MAR, APR, MAY, JUN,\
              JUL, AUG, SEP, OCT, NOV, DEC };\
// JAN=1,後續遞增,DEC=12
  • 默認從 0 開始,每項 +1。
  • 可顯式指定任意項值,後續繼續遞增。
  • 本質是 int,可隱式轉換,但建議顯式轉型 (enum months)(val)。

5.2 例:月份遍歷打印

枚舉遍歷輸出

總結與最佳實踐

  1. 結構體:首選 typedef、指針傳參、const 修飾,注意對齊填充。
  2. 聯合:用於類型雙關、硬件映射、節省互斥字段內存,慎用於可移植代碼。
  3. 位操作:掌握掩碼構建、提取、置位、翻轉常用模式。
  4. 位域:僅用於內存極度受限、位級硬件映射、協議解析場景。
  5. 枚舉:替代 #define 常量,提供類型安全與調試符號信息。

這五大特性構成了 C 語言處理複雜數據結構、底層硬件交互、高性能存儲的核心工具箱,深度掌握是成為資深 C 開發者的必經之路。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved