首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C語言 #define 宏定義完全指南:從基礎替換到進階元編程

     編輯:關於C語言

宏的本質:預處理器文本替換

`#define` 在**預處理階段**進行**標記級**替換,非文本簡潔替換。理解此點是避開所有陷阱的鑰匙。

一、簡單宏定義

#define N 5
int arr[N];  // → int arr[5];

#define N = 5
int arr[N];  // → int arr[= 5];  // 語法錯誤!

#define N 5;
int arr[N];  // → int arr[5;];  // 語法錯誤!

鐵律:替換內容**原樣放入**,不要加分號、等號、多餘符號。

二、帶參宏:運算符優先級保護

// 面積計算
#define AREA(x) ((x)*(x))  // 正確

// 錯誤示範
#define AREA(x) x*x
int s = AREA(3+2);  // → 3+2*3+2 = 15 (非 25)

// 封裝現有函數
int mult(int x, int y) { return x*y; }
#define SQUARE_AREA(x) mult(x, x)
#define RECT_AREA(x, y) mult(x, y)

防禦性寫法:每個參數加括號、整體表達式再加括號。

三、宏的三大特殊操作符

操作符名稱功能範例
#字符串化參數變為字符串字面量`#define STR(x) #x` → `STR(hello)` → `"hello"`
##標記粘合合併兩個標記為一個`#define CAT(a,b) a##b` → `CAT(var,1)` → `var1`
__VA_ARGS__可變參數配合 `...` 實現可變參宏`#define LOG(...) printf(__VA_ARGS__)`

字符串化實戰:打印表達式

#define PRINT_EXPR(expr) printf(#expr " = %d\n", expr)
PRINT_EXPR(3*4+5);  // → printf("3*4+5" " = %d\n", 3*4+5); → 輸出:3*4+5 = 17

標記粘合實戰:自動生成變量名

#define DECLARE_VAR(num) int var##num = num
DECLARE_VAR(1);  // → int var1 = 1;
DECLARE_VAR(2);  // → int var2 = 2;

可變參數宏:日誌封裝

#define LOG(level, fmt, ...) \
    fprintf(stderr, "[%s] " fmt "\n", level, ##__VA_ARGS__)

LOG("ERROR", "File %s line %d: %s", __FILE__, __LINE__, "open failed");
// GCC 支持 `##__VA_ARGS__` 自動處理前導逗號(空參數時不留逗號)

四、宏定義最佳實踐與陷阱總結

  1. 命名規範:全大寫 + 下劃線(`MAX_BUFFER_SIZE`),避免與變量衝突
  2. 括號原則:參數括號、表達式括號、複合語句用 `do{...}while(0)` 包裹
  3. 避免副作用:`MAX(i++, j++)` 導致 `i`/`j` 多次自增
  4. 優先用 `const`/`enum`/`inline` 替代:常量用 `const int N=5`,簡單函數用 `static inline`,僅在條件編譯、字符串化、標記粘合等預處理器獨有能力場景使用宏
  5. 調試技巧:`gcc -E` 查看展開結果,`#pragma message("MSG")` 編譯期輸出信息

五、經典宏模式庫

/* 數組長度(僅適用於堆上數組/字面量,不適用指針) */
#define ARRAY_LEN(arr) (sizeof(arr)/sizeof((arr)[0]))

/* 結構體成員偏移 */
#define OFFSET_OF(type, member) ((size_t)&((type*)0)->member)

/* 容器指針從成員指針反推 */
#define CONTAINER_OF(ptr, type, member) \
    ((type*)((char*)(ptr) - OFFSET_OF(type, member)))

/* 最大/最小值(GNU 擴展 typeof 避免副作用) */
#define MAX(a,b) ({ typeof(a) _a=(a), _b=(b); _a>_b?_a:_b; })

掌握宏的本質與邊界,善用預處理器能力,克制濫用,方能寫出健壯、可維護的 C 代碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved