「過馬路,左右看」不只是兒童順口溜,更蘊含先觀察主要風險方向的邏輯。軟體開發同樣存在許多「口訣」,看似死板,實為前人踩坑總結的生存法則。本文以兩個經典 C 語言口訣為例,說明為何應照著做、而非硬要反其道而行。
// 危險寫法
#define NUM_A 100
#define NUM_B 25 * 2
#define int_div(a, b) a / b
float c = int_div(NUM_A, NUM_B); // 預期 100/50=2,實際 100/25*2=8
// 正確寫法(照口訣做)
#define NUM_A (100)
#define NUM_B (25 * 2)
#define int_div(a, b) ((a) / (b))
巨集僅是文字替換,無運算子優先級概念。括號保護可確保組合語意不被外圍運算子撕裂。
// a.h 錯誤示範:定義函式本體
int max(int a, int b) { return a>b?a:b; }
// main.c
#include "a.h"
#include "a.h" // 重複包含 → 重複定義編譯錯誤
即便加上 #ifndef 防禦,跨檔包含仍會導致連結階段重複定義:
// a.h (有 guard)
#ifndef _A_H_
#define _A_H_
int max(int a, int b) { return a>b?a:b; }
#endif
// b.c #include "a.h" → 產生 max 定義
// c.c #include "a.h" → 又產生一份 max 定義
// Link 時報錯:max 多重定義
正確做法:a.h 僅放 int max(int, int); 宣告,a.c 實作本體。若極度追求效率需在標頭檔實作,請加 inline 或 static inline(C99)。
malloc 後必檢查 NULL、用完必 free、free 後指標置 NULLswitch 每個 case 以 break 結尾(刻意貫穿需註釋)== 比較,設定 epsilon 容差口訣非教條,而是經驗結晶。初學者先守,進階者悟破,大師自離。願你早日達到「見招拆招、無招勝有招」的境界。