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

C語言宏定義進階:參數括號化、# ## 操作符、多層展開與避坑指南

     編輯:關於C語言

1. 參數括號化:防止優先級陷阱

// 危險定義
#define CAL(x, y) x + y
// 調用 CAL(2,4) * CAL(2,5) → 2 + 4 * 2 + 5 = 15 (預期 42)

// 安全定義:參數與整體雙重括號
#define CAL(x, y) ((x) + (y))
// 展開 ((2) + (4)) * ((2) + (5)) = 42 ✓

鐵律:宏參數在替換處必須加括號,宏整體定義建議加外層括號。

2. 重複定義:後定義覆蓋,編譯器警告


#define PI 3.14
#define PI 10.48  // 警告:"PI" redefined,最終值 10.48

避免重複定義;若需覆蓋,先 #undef PI 再定義。

3. 危險宏:污染關鍵字/標識符


#define int char      // 災難:所有 int 變成 char
#define break continue  // 循環邏輯全亂

嚴禁定義與關鍵字、標準庫函數同名的宏。

4. 字符串化 # 與 連接 ##

操作符作用例子展開結果
#參數 → 字符串字面量#define STR(x) #xSTR(abc) → "abc"
##連接兩個標記為一個#define CAT(a,b) a##bCAT(var, 1) → var1

5. 宏參數為宏時的展開順序陷阱


#define A 100
#define STR(x) #x
#define STR_INDIRECT(x) STR(x)  // 中間層強制展開參數

STR(A)          → "A"        (參數未展開直接字符串化)
STR_INDIRECT(A) → "100"      (A 先展開為 100,再字符串化)

模式:#define PUBLIC_MACRO(x) INTERNAL_MACRO(x),內部宏執行 #/##,外部宏負責遞歸展開參數。

6. 分號陷阱:宏定義尾部不加分號


#define ADD(a,b) ((a)+(b));  // 尾部分號
x = ADD(1,2) + ADD(3,4);  // 展開 x = ((1)+(2)); + ((3)+(4)); → 語法錯誤

宏體不含分號,調用處按語句規則加分號。

7. 多語句宏:do { ... } while(0) 包裹


// 錯誤:if 後只跟第一句
#define DO(a,b) a+b; a++;
if (cond) DO(x,y); else ...  // 語法錯

// 正確:do-while(0) 形成單一語句塊
#define DO(a,b) do { a+b; a++; } while(0)
if (cond) DO(x,y); else ...  // 完美工作

8. 實戰進階模式

匿名變量生成(利用 __LINE__)


#define ANON_VAR(type) type _anon_##__LINE__
ANON_VAR(int);  // → int _anon_42; (第42行)

結構體自動填充:枚舉值 → 字符串


#define ENTRY(name) {name, #name}
enum Cmd { OPEN, CLOSE };
struct Map { int id; const char *str; };
struct Map table[] = { ENTRY(OPEN), ENTRY(CLOSE) };
// → {{OPEN, "OPEN"}, {CLOSE, "CLOSE"}}

文件名記錄


#define FILE_NAME_STR __FILE__
static const char *this_file = FILE_NAME_STR;

類型最大值字符串長度


#define TYPE_BUF_SIZE(type) (sizeof(#type))  // 需兩層展開
char buf[TYPE_BUF_SIZE(INT_MAX)];  // → char buf[sizeof("2147483647")] → 11

標準預定義宏

  • __LINE__:當前行號 (int)
  • __FILE__:當前文件名 (字符串)
  • __DATE__:編譯日期 "Mmm dd yyyy"
  • __TIME__:編譯時間 "hh:mm:ss"
  • __STDC__:符合標準則為 1

調試宏模板


#ifdef DEBUG
#define LOG(fmt, ...) printf("[%s:%d] " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__)
#else
#define LOG(fmt, ...)
#endif
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved