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

C 語言進階教學:位域、位運算與 typedef 完整指南

     編輯:關於C語言

位運算是 C 語言最貼近硬體的特性之一,廣泛應用於嵌入式暫存器操作、網路協定封包解析、壓縮儲存、加密演算等場合。本文系統整理位域、位運算子、複合指派、typedef 別名定義等核心知識,並提供實戰範例與最佳實務建議。

位域:結構體內的位元級記憶體佈局

語法與限制

struct BitField {
    unsigned int a : 1;   // 1 bit
    unsigned int b : 3;   // 3 bits
    unsigned int c : 4;   // 4 bits
};  // 總共 8 bits,通常壓縮在 1 個 unsigned int (16/32 bits) 內
  • 僅限 int、unsigned int、signed int(C99 允許 _Bool)。
  • 寬度不可超過底層型別位寬。
  • 不可取位址(&bf.a 錯誤),不可跨儲存單元(編譯器自動對齊)。
  • 記憶體佈局順序:實作定義(通常從低位到高位,但位元序視 CPU 端序而定)。

存取與指標操作

struct BitField bf = {1, 7, 15};
struct BitField *p = &bf;
p->a = 0;
p->b &= 3;   // 7 & 3 = 3
p->c |= 1;   // 15 | 1 = 15
printf("%d,%d,%d\n", p->a, p->b, p->c); // 0,3,15

位域成員可直接當整數運算,編譯器自動生成遮罩、位移指令。

實戰:網路封包標頭解析

#pragma pack(1)
struct IPv4Header {
    unsigned int version : 4;
    unsigned int ihl     : 4;
    unsigned int dscp    : 6;
    unsigned int ecn     : 2;
    unsigned int total_len : 16;
    // ... 其他欄位
};
#pragma pack()
// 直接讀取 version = hdr->version,無需手動位移遮罩

位運算子完整速查表

運算子名稱範例結果說明
&按位與0b1100 & 0b10100b1000(兩邊皆 1 才為 1)
|按位或0b1100 | 0b10100b1110(任一為 1 即為 1)
^按位異或0b1100 ^ 0b10100b0110(不同為 1,相同為 0)
~按位取反~0b11000b...0011(視型別寬度補齊)
<<左移0b0011 << 20b1100(低位補 0,等價 ×4)
>>右移0b1100 >> 20b0011(無符號補 0,有符號算術移位保號)

複合指派運算子

x &= y;  // x = x & y
x |= y;  // x = x | y
x ^= y;  // x = x ^ y
x <<= n; // x = x << n
x >>= n; // x = x >> n

經典位技巧

// 清除第 n 位
x &= ~(1U << n);
// 設定第 n 位
x |= (1U << n);
// 翻轉第 n 位
x ^= (1U << n);
// 測試第 n 位
bool is_set = (x >> n) & 1U;
// 取最低位 1
x & -x;           // 利用二補數特性
// 清除最低位 1
x &= (x - 1);     // Brian Kernighan 演算法核心
// 判斷 2 的冪次
(x & (x - 1)) == 0 && x != 0;
// 交換兩數(無暫存變數)
a ^= b; b ^= a; a ^= b;

typedef:型別別名與可讀性增強

基本語法

typedef int INTEGER;           // 標量別名
typedef char NAME[20];         // 陣列別名
typedef struct { ... } STU;    // 結構體別名
typedef void (*Handler)(int);  // 函式指標別名

typedef vs #define

特性typedef#define
處理階段編譯期(語義分析)預處理期(文字替換)
指標宣告typedef int *IntPtr; IntPtr a, b; 皆為 int*#define IntPtr int* IntPtr a, b; → int* a, b; (b 是 int)
作用域遵循區塊作用域全域文本替換
除錯資訊保留型別名稱無型別資訊

結論:永遠優先使用 typedef 定義型別別名,避免 #define 造成指標宣告陷阱。

本章小結:七大核心觀念

  1. 枚舉 是獨立型別,元素為常值,不可動態輸入,printf 僅能印順序值。
  2. 位運算 以二進制位為單位,分邏輯(& | ^ ~)與移位(<< >>)兩類。
  3. 複合指派 簡化讀修寫模式,生成更高效機器碼。
  4. 位域 本質是結構體,成員按位分配記憶體,支援指標存取。
  5. 位域優勢:資料壓縮儲存、暫存器映射、協定欄位對齊。
  6. typedef 提供語義級別名,增強可讀性,編譯期處理比巨集安全。
  7. 移植性提醒:位域佈局、右移算術/邏輯、int 寬度均為實作定義,跨平台需謹慎。

練習題

  1. 用位域定義一個 16-bit 的 RGB565 色彩結構體,並寫出封裝/解碼函式。
  2. 實作 int count_bits(unsigned x) 計算 1 的個數(查表法 / Kernighan 法 / 編譯器內建 __builtin_popcount)。
  3. 說明為何 typedef char *StrPtr; StrPtr a, b; 使 a、b 皆為 char*,而 #define StrPtr char* 會導致 b 為 char。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved