| 維度 | 位運算 (`&` `|` `^` `~`) | 邏輯運算 (`&&` `||` `!`) |
|---|---|---|
| 操作對象 | 整型位模式 | 標量真值(0=假,非0=真) |
| 結果類型 | 整型(同位寬) | `int`(0 或 1) |
| 運算粒度 | 逐位獨立 | 整體真值 |
| 短路求值 | 無 | 有(`&&` `||`) |
| 優先級 | 較高(`~` > `<<` > `&` > `^` > `|`) | 較低(`!` > `&&` > `||`) |
| 典型用途 | 掩碼、標志位、數學優化 | 條件判斷、流程控制 |
void print_bits(int x, int bits) {
for (int i = bits - 1; i >= 0; i--)
putchar((x & (1 << i)) ? '1' : '0');
putchar('\n');
}
void xor_swap(int *x, int *y) {
if (x != y) { // 關鍵:防止同地址歸零
*x ^= *y;
*y ^= *x;
*x ^= *y;
}
}
數學證明:`a ^= b; b ^= a; a ^= b` 等價於交換。現代 CPU 有寫後讀依賴,反而比 `tmp` 慢,僅作教學。
int a = 32, b = 43;
printf("!a=%d, a||b=%d, a&&b=%d\n", !a, a||b, a&&b); // 0, 1, 1
// 短路演示:b-- 不會執行,因 a++ 為真(33)
printf("a++||b-- = %d\n", a++ || b--); // 輸出 1
printf("a=%d, b=%d\n", a, b); // a=33, b=43(b 未遞減)
C 標準規定:`&&` `||` `!` 結果嚴格為 `0` 或 `1`(`int` 類型)。
// 錯誤:位與不短路,且結果非 0/1
if (ptr & ptr->valid) // 即使 ptr 為 NULL,仍會嘗試訪問 ptr->valid → 崩潰
// 正確:邏輯與短路保護
if (ptr && ptr->valid)
#define FLAG_A (1 << 0)
#define FLAG_B (1 << 1)
unsigned int flags = FLAG_A | FLAG_B;
// 檢查單個標志:位與
if (flags & FLAG_A) { ... }
// 檢查多個標志全滿足:位與 + 比較
if ((flags & (FLAG_A | FLAG_B)) == (FLAG_A | FLAG_B)) { ... }
// 邏輯運算無法直接檢查位模式
// 位運算優先級低於 ==
if (x & 1 == 0) // 解析為 x & (1 == 0) → x & 0 → 恆為 0
// 正確
if ((x & 1) == 0)
// 邏輯運算優先級低於關係運算
if (a > 0 && b > 0) // 正確,等價於 (a > 0) && (b > 0)
#include <stdio.h>
int main(void) {
int a = 19, b = 38; // 00010011, 00100110
printf("=== 位運算 ===\n");
print_bits(a, 8); print_bits(b, 8);
printf("~a: "); print_bits(~a, 8);
printf("a&b: "); print_bits(a & b, 8);
printf("a|b: "); print_bits(a | b, 8);
printf("a^b: "); print_bits(a ^ b, 8);
printf("\n=== 邏輯運算 ===\n");
int x = 32, y = 43;
printf("x=%d, y=%d\n", x, y);
printf("!x=%d, x||y=%d, x&&y=%d\n", !x, x||y, x&&y);
// 短路副作用演示
printf("x++||y-- = %d\n", x++ || y--);
printf("x=%d, y=%d (y 未變)\n", x, y);
return 0;
}