C 語言之所以成為系統級開發的首選,核心在於其記憶體模型完美映射了馮·諾伊曼架構,且語言本身提供了豐富的底層操作支援。本文將透過四個經典問題,深入剖析 C 語言的核心底層機制。
移位運算子 >> 和 << 將變量的二進制位向右或向左移動。關鍵差異在於右移時高位如何填充:
最佳實踐:若需確保高位補 0,請明確使用 unsigned 類型。
若資料型別佔 n 位(如 32 位 int),移位量必須滿足 0 <= 位數 < n。超出此範圍屬於未定義行為。例如:
n << 31、n << 0 合法n << 32、n << -1 非法注意:即使採用算術右移,有符號整數右移也不等同於除以 2。例如 -1 >> 1 結果為 -1,而非 0。
位段允許在結構中指定成員佔用的確切位數,極大節省記憶體並簡化位操作。
struct RPR_ATD_TLV_HEADER {
ULONG res1: 6;
ULONG type: 10;
ULONG res2: 6;
ULONG length: 10;
};
一般形式:資料類型 成員名: 位寬;,位寬為 0~15 的整型常數。成員名可省略,用於對齊填充。
struct {
unsigned incon: 8; // 低位元組 0~7 位
unsigned txcolor: 4; // 高位元組 0~3 位
unsigned bgcolor: 3; // 高位元組 4~6 位
unsigned blink: 1; // 高位元組第 7 位
} ch;
存取方式與普通結構相同:ch.bgcolor。位段也可與普通成員混用,例如用兩個 1-bit 位段分別表示「工人狀態」與「薪資發放狀態」,僅佔 1 個位元組即可儲存兩項資訊。
警示:賦值不得超出位段容許範圍,否則會發生截斷。
字節對齊決定結構成員在記憶體中的排列位置,直接影響 sizeof 結果與跨 DLL/進程的資料交換正確性。
long 為 4)。#pragma pack(n) 強制設定,#pragma pack() 恢復預設。min(指定對齊, 自然對齊)。結構整體對齊取所有成員實際對齊的最大值。#pragma pack(8)
struct STest1 { char ch1; long lo1; char ch2; } test1;
#pragma pack()
// Align = 4, sizeof = 12
// 記憶體佈局:ch1(1) + padding(3) + lo1(4) + ch2(1) + padding(3)
#pragma pack(2)
struct STest2 { char ch3; STest1 test; } test2;
#pragma pack()
// Align = 2, sizeof = 14
// 內部 STest1 受 pack(2) 影響重新排列
#pragma pack,阻礙編譯器優化。#pragma pack(n) 後勿 include 其他頭文件,防止對齊值被竄改。C 語言完整支援位運算,可直接操作位元組或字的二進制位,僅適用於字元與整數型別。
| 運算符 | 功能 |
|---|---|
& | 位邏輯 AND |
| | 位邏輯 OR |
^ | 位邏輯 XOR |
~ | 位邏輯 NOT (取反) |
>> | 右移 |
<< | 左移 |
10 & 12 = 8)。&&、|| 具備短路求值;&、| 無短路,逐位運算。範例:x = 7 時,x && 8 為真 (1),但 x & 8 為 0。
掌握移位語義、位段封裝、字節對齊規則與位運算細節,是寫出高效、可移植、符合規範 C 代碼的基石。實戰中請始終牢記:明確類型、避免未定義行為、統一對齊約定。