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

C語言巨集替換機制詳解:為何 #define out(x) "billd##(x)##.gif" 無法在字串常數內展開參數?

     編輯:C 語言問答

核心規則:巨集參數不會在字串常數內展開

C 標準規定:#define 替換發生於**前置處理階段**,字串常數 ("...") 內的字元**不參與**巨集參數替換,也不進行 ## 連接。

錯誤嘗試分析


#define out(x) "billd##(x)##.gif"  // 錯誤:字串內不處理
#define out(x) "billd"##(x)##".gif" // 錯誤:## 不能連接字串常數與括號
#define out(x) "billd"##"(x)"##".gif" // 錯誤:同理

以上皆會輸出字面文字 billd(x).gif 或編譯錯誤。

正確做法:分離字串與參數,利用字串常數自動連接


#define STR(x) #x           // 字串化運算子:將參數變為字串常數
#define CAT(a,b) a##b       // 連接運算子

#define OUT(x) "billd" STR(x) ".gif"
// 展開過程:OUT(5) → "billd" STR(5) ".gif" → "billd" "5" ".gif" → "billd5.gif"

進階:可變參數巨集 (C99)


#define FMT(fmt, ...) printf(fmt, __VA_ARGS__)
// 使用:FMT("billd%d.gif\n", 5);

為什麼不能直接在字串裡用 ##?

  • ## 是**記號連接**,運作於**前置處理記號**層級,字串常數是**單一記號**,內部結構不可見。
  • 字串化 # 將記號轉為字串常數,**發生在參數替換之後**,因此可用於參數值。

最佳實踐

  1. 需要字串拼接 → 用 #x 字串化參數,依賴相鄰字串常數自動連接。
  2. 需要格式化輸出 → 直接用 printf/snprintf,勿嘗試巨集模擬。
  3. 巨集命名全大寫,參數用括號包裹,避免副作用:#define SQR(x) ((x)*(x))。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved