記錄 C 語言開發中易混淆、易出錯的知識點,涵蓋運算符優先級、記憶體佈局、指標運算、編譯鏈接等核心領域,作為查漏補缺參考。
x = y > z ? y : z; // 正確:條件 ? 真值 : 假值 // 切記括號:x = (y > z) ? y : z; 避免優先級歧義
+ - > 移位 << >> > 關係 < > > 位與 & > 位異或 ^ > 位或 | > 邏輯與 && > 邏輯或 || > 三元 ?: > 賦值 =a << 8 + b 實際為 a << (8 + b),應寫 (a << 8) + bint i = 0; sizeof(i++); // 返回 4 (int 大小),i 不會自增! // sizeof 不計算表達式值,僅根據類型推導大小 // strlen 運行期計算,遇 \0 停止
// 錯誤示範 #define Uint8 unsigned char typedef Uint8 MyUint8; // 展開為 typedef unsigned char MyUint8; 正確 // 但若 #define PINT int* typedef PINT MyPtr; // 展開為 typedef int* MyPtr; 正確 // 危險:#define 文本替換,typedef 語義定義,勿混用
printf("%%\n"); // 雙重 %% 轉義輸出單個 %
if (a && b) // 邏輯與:短路,結果 0/1 if (a & b) // 位與:逐位運算,結果數值
!a + b 等價於 (!a) + b // 邏輯非優先級最高 ~a + b 等價於 (~a) + b // 位非優先級同單目運算符
strcpy 複製含 \0 的完整字串strlen 統計 \0 前字符數,不含 \0// 第 5 位置 1 A |= (1 << 5); // 第 5 位清 0 A &= ~(1 << 5); // 第 5 位取反 A ^= (1 << 5);
union Data { int i; float f; } u;
u.i = 10; // 必須用 . 成員訪問
printf("0x%08x\n", val); // 8位寬度,前導補 0
函數調用棧幀包含:參數、返回地址 (EIP)、舊幀基址 (EBP)、局部變數、暫存寄存器。x86 向下增長(高地址→低地址)。
struct Test { char x1; short x2; float x3; char x4; };
// x1: offset 0, size 1
// padding 1 byte (對齊 short 2字節)
// x2: offset 2, size 2
// x3: offset 4, size 4 (自然對齊)
// x4: offset 8, size 1
// padding 3 bytes (結構體整體對齊到最大成員 4 字節)
// 總大小 = 12 字節
memset(ptr, 0, 100); // 將 100 字節置 0 memcpy(dst, src, n); // 複製 n 字節,記憶體不可重疊 memmove(dst, src, n); // 安全複製,允許重疊
每進程獨立地址空間,數據段複製,全局變量互不干擾,無競爭。
static struct { char *name; int offset; } _reg_list[] = {
{"reg1", 0x10}, {"reg2", 0x20}
};
for (i=0; i<10; i++) { if (cond) break; }
// break 後 i 不再自增,保持當前值
temp = (temp + 1) & 7; // 0→1→...→7→0,位運算替代 %8
unsigned char *p = arr; // 正確:指針賦值給同類型指針 unsigned int p1 = (unsigned int)arr; // 需強轉:指針轉整數 unsigned char *p_arr[10]; // 指針陣列:10個 char* unsigned char (*p_arr2)[10]; // 陣列指針:指向 10 char 的陣列
if-else if:互斥,命中一個後跳過其餘判斷if:獨立判斷,可能多個分支均執行char a[3][4]; char (*p)[4] = a; // 正確:行指針,指向 4 char 的陣列 char **p2 = a; // 錯誤:類型不匹配,a 不是 char**
a:類型 char (*)[4],值為首元素地址 &a[0][0]&a:類型 char (*)[3][4],值同樣是首地址,但 &a+1 偏移整個陣列大小 (12*sizeof(char))fseek(fp, 0, SEEK_END); long size = ftell(fp); fseek(fp, 0, SEEK_SET); // 復位
a ^= b; b ^= a; a ^= b; // 異或交換 a += b; b = a - b; a -= b; // 加減交換(注意溢出)
這 30 個筆記覆蓋了 C 語言從語法細節到底層實現的關鍵點。建議開發者:
-Wall -Wextra -pedantic