性能優化不僅是編譯器的事,更是代碼設計層面的藝術。本文精選十大源碼級優化模式,涵蓋函數調用、內存訪問、數據佈局、算法優化、防禦性編程,每項均附帶反面教材與正確範例,助你寫出又快又穩的 C 代碼。
// ❌ 慢:每次迭代調用 strlen for (int i = 0; i < strlen(s); ++i) putchar(s[i]); // ✅ 快:提取不變量 size_t len = strlen(s); for (int i = 0; i < len; ++i) putchar(s[i]);
原則:循環不變量外提,編譯器不一定能自動優化(尤其涉及函數調用)。
// ❌ 5 次內存訪問 *num1 = *num2; *num1 += *num2; return *num1; // ✅ 2 次內存訪問 *num1 = 2 * *num2; return *num1;
原則:寄存器變量、局部變量暫存中間結果,減少 Load/Store 指令。
// ❌ 12 字節 (假設 4 字節對齊)
struct { char c; int i; short s; } s1;
// 佈局: c[0], pad[1-3], i[4-7], s[8-9], pad[10-11]
// ✅ 8 字節
struct { char c; short s; int i; } s2;
// 佈局: c[0], s[1-2], pad[3], i[4-7]
技巧:按類型大小降序排列(大→小),或將熱點字段前置提高緩存命中。
-Wsign-compare 捕獲符號混用 Bug。// ❌ 易誤寫為 =,運行時 Bug
if (x = 1) { ... }
// ✅ 編譯期報錯
if (1 == x) { ... }
這是「雅各布森簽名」防禦性編程經典模式。
// ❌ 宏陷阱 #define INT_PTR int* INT_PTR a, b; // a 是 int*,b 是 int! // ✅ typedef 語義正確 typedef int* INT_PTR; INT_PTR a, b; // 皆為 int*
// ❌ 指數級重複
int fib(int n) { return n<2?1:fib(n-1)+fib(n-2); }
// ✅ O(n) 備忘錄
int fib_memo(int n) {
static int memo[1000] = { [0]=1, [1]=1 };
if (memo[n]) return memo[n];
return memo[n] = fib_memo(n-1) + fib_memo(n-2);
}
適用於重疊子問題最優子結構場景(DP 本質)。
// 懸空指針
int *p = malloc(sizeof(int));
free(p);
// p 現在是懸空指針
p = NULL; // 立即置空
// 野指針
int *q; // 未初始化
// printf("%d", *q); // 崩潰/輸出垃圾
q = NULL; // 定義即初始化
鐵律:指針聲明即初始化;free 即置 NULL;所有權轉移時雙方協議清晰。
malloc/calloc/realloc 對應唯一 free。return 皆需釋放(goto cleanup 模式)。| 類別 | 檢查項 |
|---|---|
| 循環 | 不變量外提、減少函數調用、展開小循環 |
| 內存 | 結構體對齊、熱點字段前置、減少間接訪問 |
| 類型 | 無符號優先、避免隱式轉換、常量左置 |
| 函數 | static 內部函數、參數≤3、單一職責、短小精悍 |
| 安全 | 指針初始化、釋放置空、備忘錄去重、所有權清晰 |
性能優化的最高境界是正確性前提下的簡潔。先寫清晰正確的代碼,再用 Profiler 定位熱點,針對性應用上述模式,方為正道。