| 編碼 | 正數 | 負數 | 0 的表示 | 範圍(8位) |
|---|---|---|---|---|
| 原碼 | 符號位+絕對值 | 符號位+絕對值 | +0 `00000000`、-0 `10000000` | [-127, +127] |
| 反碼 | 同原碼 | 符號位不變,其餘位取反 | +0 `00000000`、-0 `11111111` | [-127, +127] |
| 補碼 | 同原碼 | 反碼+1 | 唯一 `00000000` | [-128, +127] |
驗證:`1 + (-1)` 在補碼中 → `00000001 + 11111111 = 100000000` → 截斷高位 → `00000000` = 0 ✓
| 運算符 | 名稱 | 規則 | 範例(9=1001, 5=0101) | 核心規律 |
|---|---|---|---|---|
| `&` | 按位與 | 同為1得1 | 9&5=1 (0001) | &1 保留、&0 清零 |
| `|` | 按位或 | 有1得1 | 9|5=13 (1101) | |1 置位、|0 保留 |
| `^` | 按位異或 | 不同得1 | 9^5=12 (1100) | 同值得0、異值得1、x^x=0、x^0=x |
| `~` | 按位取反 | 0↔1(含符號位) | ~9 = -10 | 負數補碼存儲,~x = -x-1 |
| `<<` | 左移 | 高位丟棄,低位補0 | 5<<1 = 10 | x< |
| `>>` | 右移 | 低位丟棄,符號位複製 | -10>>1 = -5 | 算術右移保持符號,x>>n ≡ x/2ⁿ |
if (n & 1) puts("奇數"); else puts("偶數"); // 比 n%2 快,無分支預測失敗
a ^= b; b ^= a; a ^= b; // 任意類型,無溢出風險
// 判斷是否為 2 的冪次
bool is_pow2(unsigned n) { return n && !(n & (n-1)); }
// 向上對齊到 2 的冪次(如內存對齊)
size_t align_up(size_t n, size_t alignment) {
return (n + alignment - 1) & ~(alignment - 1);
}
#define BIT(n) (1U << (n))
#define GET(x, n) ((x) & BIT(n))
#define SET(x, n) ((x) |= BIT(n))
#define CLR(x, n) ((x) &= ~BIT(n))
#define FLIP(x, n) ((x) ^= BIT(n))
有限位寬 `w` 下,補碼運算等價於 **模 `2^w` 同餘運算**:
這解釋了為什麼 `unsigned` 與 `signed` 混合運算按無符號規則進行(C 標準規定),且補碼加減乘指令完全通用。