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

C語言預處理器深度解析:宏、字符串化、可變參數與預定義宏

     編輯:關於C語言

預處理器的兩大核心價值

  1. 集中管理常量:修改一處,重新編譯即生效,避免硬編碼散落
  2. 避免函數調用開銷:宏展開為內聯代碼,如 getchar、putchar 常被實現為宏

帶參數宏的陷阱與最佳實踐

對比三種絕對值宏:

#define ABS(x)  x>0?x:-x           // 危險:無括號保護
#define ABS1(x) (x)>0?(x):-(x)      // 部分保護
#define ABS2(x) ((x)>0?(x):-(x))    // 完整保護(推薦)

測試代碼:

int a=1, b=4;
printf("%d\n", ABS(a-b));   // -5 錯誤:展開為 1-4>0?1-4:-1-4
printf("%d\n", ABS1(a-b));  // 3 正確
int c=4, d=1;
printf("%d\n", ABS1(c-d)-1); // 3 錯誤:展開為 (4-1)>0?(4-1):-(4-1)-1
printf("%d\n", ABS2(c-d)-1); // 2 正確

鐵律:宏參數在定義中每次出現都要加括號,整個表達式也要加外層括號。

# 運算符:字符串化

#define PSQR(x) printf("The square of "#x" is %d\n", (x)*(x))
PSQR(y);      // The square of y is 25
PSQR(2+4);    // The square of 2+4 is 36

#x 將參數轉為字符串字面量,便於調試輸出。

可變參數宏:... 與 __VA_ARGS__

#define PR(X, ...) printf("Message " #X ": " __VA_ARGS__)
PR(1, "X=%g\n", x);
PR(2, "X=%.2f, y=%.4f\n", x, y);
// 編譯需鏈接數學庫:gcc variadic.c -lm

注意:... 只能替代最後的參數,C99 標準引入。

常用預定義宏

宏含義示例輸出
__FILE__當前源文件名predef.c
__DATE__編譯日期Dec 13 2013
__TIME__編譯時間22:52:07
__LINE__當前行號10
__func__當前函數名(C99)main
__STDC_VERSION__C 標準版本號199901L (C99)

這些宏在日誌輸出、調試斷言、版本資訊嵌入等場景極其有用。

預處理器不進行計算

切記:預處理器只做文本替換,不懂 C 語法,不做類型檢查,不計算常量表達式(除 #if 條件編譯外)。濫用宏易導致難以調試的錯誤,能用 const/inline/enum 替代時優先考慮。

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