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

C 語言 ## 連接符(Token-Pasting Operator)完整用法指南

     編輯:關於C語言

什麼是 ## 運算符

在 C 語言宏定義中,`##` 稱為標記連接運算符(Token-Pasting Operator)。它的作用是在宏展開時,將兩個獨立的預處理標記(Token)連接成一個新的標記。

基本語法


#define MACRO(a, b) a ## b
MACRO(var, 1)  // 展開為 var1

核心用法場景

1. 變參宏中處理可選參數(GCC 擴展)

C99 標準引入 `__VA_ARGS__`,GCC 進一步支援 `##__VA_ARGS__` 解決「參數為空時多出逗號」的問題:


// 錯誤寫法:調用 debug("Test") 時展開為 fprintf(stderr, "Test" , ) —— 多出逗號,編譯失敗
#define debug(format, args...) fprintf(stderr, format, args)

// 正確寫法:## 會在 __VA_ARGS__ 為空時「吃掉」前面的逗號
#define debug(format, ...) fprintf(stderr, format, ##__VA_ARGS__)

void main(void) {
    debug("Test\n");        // ✓ 展開為 fprintf(stderr, "Test\n")
    debug("Value: %d\n", 42); // ✓ 展開為 fprintf(stderr, "Value: %d\n", 42)
}

2. 構建標識符(代碼生成)


#define DECLARE_FUNC(name) void func_##name(void)
DECLARE_FUNC(init);   // 展開為 void func_init(void)
DECLARE_FUNC(cleanup); // 展開為 void func_cleanup(void)

#define MAKE_VAR(type, name) type var_##name
MAKE_VAR(int, count);  // int var_count;

3. 字符串化與連接結合(`#` + `##`)


#define STRINGIFY(x) #x
#define CONCAT_AND_STRINGIFY(a, b) STRINGIFY(a ## b)

CONCAT_AND_STRINGIFY(Hello, World)  // "HelloWorld"

標準與編譯器差異

場景C99 `__VA_ARGS__`GCC `##__VA_ARGS__`MSVC `__VA_ARGS__`
參數為空保留逗號,可能報錯自動移除前置逗號不支援 ##,需雙層宏
有參數正常工作正常工作正常工作

注意事項

  • `##` 不能出現在宏定義的開頭或結尾
  • 連接後必須形成合法的預處理標記(標識符、關鍵字、常量等)
  • 連接發生在宏參數替換之後,參數若為宏會先展開
  • 避免濫用導致代碼難以閱讀和調試

實戰範例:日誌宏


#define LOG_LEVEL_INFO  1
#define LOG_LEVEL_DEBUG 2
#define LOG_LEVEL_ERROR 3

#define LOG(level, fmt, ...) \
    do { \
        if (CURRENT_LOG_LEVEL >= level) { \
            fprintf(stderr, "[%s:%d] " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); \
        } \
    } while(0)

// 使用
LOG(LOG_LEVEL_INFO, "Server started on port %d", 8080);
LOG(LOG_LEVEL_DEBUG, "Connection from %s", client_ip);
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved