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

VC 宏編程精講:## 連接符與 # 字符串化操作符深度解析

     編輯:關於VC++

核心宏定義速查

宏定義功能示例結果
#define EC(x) L##xToken 連接:將 L 與參數融合為寬字符字面量EC(hello)L"hello"
#define Conn(x,y) x##yToken 連接:融合兩個參數Conn(123,456)123456
#define ToChar(x) #@x字符化:用單引號包裹參數ToChar(1)'1'
#define ToString(x) #x字符串化:用雙引號包裹參數ToString(123132)"123132"

## 連接符深度解析

## 由兩個井號組成,用於帶參數宏定義中將兩個 token(語法最小單元)連接成新 token。注意:它不能位於第一個或最後一個 token 位置。

經典範例

int n = Conn(123, 456);        // n = 123456
char* str = Conn("asdf", "adf"); // str = "asdfadf"

# 字符串化操作符

# 將傳入參數視為字面文本,用雙引號包裹成字符串常量。#@ 則用單引號包裹成字符常量。

邊界行為

  • ToChar(123) → '3'(取最後一字符)
  • 參數超過 4 字符 → 編譯錯誤 C2015: too many characters in constant

MSDN 經典案例拆解

#define paster(n) printf("token" #n " = %d", token##n)

int token9 = 9;
paster(9);

預處理展開:

printf("token" "9" " = %d", token9);
// 即 printf("token9 = %d", token9);
// 輸出:token9 = 9

關鍵機制:9 同時被 #n 字符串化為 "9",又被 token##n 連接為 token9。

常見陷阱與技巧

1. printf("" #name "") 為何輸出 name 而非 "#name"?

#define display(name) printf("" #name "")
display(name);  // 展開為 printf("" "name" "") → printf("name")

相鄰字符串字面量自動連接,#name 變為 "name",外層空串 "" 合併後等價於 printf("name")。

2. print(x) 系列實驗

#define print(x) printf(#x)

print(123);        // printf("123")        → 輸出 123
print("123");      // printf("\"123\"")    → 輸出 "123"
print("\n");       // printf("\"\\n\"")    → 輸出 "\n"

# 會保留參數原始拼寫,包括引號與轉義字符。

官方術語對照

  • ##:Token-pasting operator(標記連接操作符)
  • #:Stringizing operator(字符串化操作符)
  • #@:Charizing operator(字符化操作符,Microsoft 擴展)

實戰建議

  1. 宏參數連接時,兩側必須各有一個 token,否則編譯報錯
  2. 字符串化時,參數中的 " 會自動轉義為 \",\ 變為 \\
  3. 調試宏展開:MSVC 使用 /P 編譯選項生成 .i 預處理文件
  4. 避免濫用宏實現複雜邏輯,現代 C++ 優先考慮 constexpr、模板、內聯函數
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved