C 語言巨集(macro)功能強大但陷阱眾多。本文系統整理函數式巨集的四大典型用法與易錯點,配合代碼示例幫助開發者避開坑洞,寫出健壯的巨集代碼。
#define FUNC() do_something()
錯誤用法:
FUNC() = 10; // 編譯錯誤
x = FUNC(); // 若無返回值亦錯誤
原因:巨集展開後只是語句序列,不具備表達式屬性。
#define FUNC() ({ do_something(); return_value; })
正確用法:
int x = FUNC(); // 可作右值
FUNC(); // 可作語句
注意:
FUNC();do { ... } while(0)#define MACRO() do { \
stmt1; \
stmt2; \
} while(0)
優點:
MACRO(); 符合習慣if-else 中不會產生「懸空 else」問題缺點:無法作為賦值運算的左/右值。
({ ... }) 形式(GCC 擴展)#define FUNC() ({ \
int tmp = compute(); \
tmp; /* 最後一個表達式為返回值 */ \
})
可直接賦值:int x = FUNC();
do { ... } while(0) + 輸出參數#define FUNC(out) do { \
int tmp = compute(); \
*(out) = tmp; \
} while(0)
調用方式:
int result;
FUNC(&result);
| 需求 | 推薦寫法 | 可賦值 | 標準C |
|---|---|---|---|
| 單語句、無返回值 | #define M() stmt | 否 | 是 |
| 多語句、無返回值 | do{...}while(0) | 否 | 是 |
| 需返回值 | ({...}) (GCC) 或 輸出參數 | 是 | 否/是 |
#define MAX(a,b) ((a)>(b)?(a):(b))do{...}while(0)MAX(i++, j))