#define MAX 1000
for (int i = 0; i < MAX; ++i) { ... } // 預處理階段直接替換為 1000
#define MAX(x, y) ((x) > (y) ? (x) : (y)) // 正確:參數與整體加括號
// 錯誤範例
#define ADD(a, b) a + b
int c = 10 * ADD(2, 3); // 展開為 10 * 2 + 3 = 23,非預期的 50
鐵律:巨集定義中,每個參數與整個表達式都要用括號包裹。
#define PTR int*
PTR a, b; // 展開為 int* a, b; → a 是指標,b 是 int(陷阱!)
typedef int* Ptr;
Ptr a, b; // a、b 皆為 int*(正確)
型別別名請用 typedef,巨集僅做文字替換,不具備型別語意。
#define STR(x) #x
#define CONCAT(a, b) a##b
STR(hello) → "hello"
CONCAT(var, 1) → var1
應用場景:自動生成變數名、編譯期字串化除錯資訊。
#define SAFE_FREE(p) do { free(p); (p) = NULL; } while(0)
if (cond) SAFE_FREE(ptr); // 安全:單一語句,配合分號無誤
else ...
do { ... } while(0) 確保巨集在 if-else、循環體中表現如單一語句,避免「分號吞噬」與「多語句分組」問題。
// 結構體成員偏移量(Linux 核心風格)
#define offsetof(TYPE, MEMBER) ((size_t)&((TYPE *)0)->MEMBER)
// 從成員指標反推結構體指標
#define container_of(ptr, TYPE, MEMBER) \
((TYPE *)((char *)(ptr) - offsetof(TYPE, MEMBER)))
// C11 靜態斷言
#define STATIC_ASSERT(cond) _Static_assert(cond, #cond)
__FILE__、__LINE__、__func__#ifdef DEBUG
#define LOG(fmt, ...) fprintf(stderr, "[%s:%d] " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__)
#else
#define LOG(fmt, ...) ((void)0)
#endif
釋出版本自動消除,零開銷。
const/enum/inline/template 替代巨集(型別安全、作用域受控)。typedef/using。#、##、__VA_ARGS__ 實現元程式設計,但保持可讀性。