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

C++ 前處理器深度解析:#、## 與字串字面量合併機制

     編輯:C++ 入門

C++ 宏編程核心:字串化(#)與標記連接(##)運算符詳解

在 C++ 宏編程中,# 和 ## 是兩個極其強大但常被誤解的前處理運算符。掌握它們的行為細節,對於編寫靈活、健壯的巨集至關重要。

前置知識:字串字面量的自動合併

C++ 編譯器會在預處理階段自動合併相鄰的字串字面量,無論中間是否有空白字符:

const char* p1 = "Hello," "World!";  // 等價於 "Hello,World!"
const char* p2 = "Hello,"  "World!"; // 多個空白同理
const char* p3 = "Hello,""World!";   // 無空白也合併
const char* p4 = "Hello,World!";     // 完整字串
// 以上四種寫法編譯後完全等價,常量段僅存一份 "Hello,World!"

這一特性是理解 # 運算符行為的基礎。

字串化運算符 (#)

作用:將宏參數不經擴展直接轉換為字串字面量。

關鍵規則:

  • 參數兩側的空白字符會被忽略
  • 參數內部多個連續空白會壓縮為單個空白
  • 參數中包含 " 或 \ 等特殊字符時,會自動添加轉義字符 \

經典範例(來自 MSDN):

#define F abc
#define B def
#define FB(arg) #arg
#define FB1(arg) FB(arg)

FB(F B)   // 展開為 "F B"      —— 參數未擴展,直接字串化
FB1(F B)  // 展開為 "abc def"  —— 參數先擴展為 "abc def",再字串化

預處理器輸出驗證:

"F B";
"abc def";

標記連接運算符 (##)

作用:將多個預處理標記連接成單一標記。

關鍵規則:

  • 不能出現在宏定義的首尾
  • 前後空白可有可無
  • 連接結果必須是合法的預處理標記

實戰範例:

#define paster(n) printf_s("token" #n " = %d", token##n)
int token9 = 9;
paster(9);

預處理展開過程:

paster(9);
printf_s("token" #9 " = %d", token##9);
printf_s("token" "9" " = %d", token9);
printf_s("token9 = %d", token9);

最佳實踐建議

  1. 使用 # 時注意參數擴展時機,善用雙層宏強制擴展
  2. ## 連接後若產生非法標記會導致編譯錯誤,需謹慎設計
  3. 複雜宏建議分層定義,便於調試與維護
  4. 參考 MSDN 官方文檔獲取最權威規範說明
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved