C宏中的##(token pasting)

Gold_stein發表於2024-09-04

C宏中的##(token pasting)

以下內容來自GPT

在 C 和 C++ 中,## 運算子稱為“token pasting”運算子或“貼上”運算子,用於宏定義中。當使用 ## 運算子時,它會將前後的標記(token)直接拼接在一起。在 __VA_ARGS__ 前面使用 ## 運算子有一個特定的用途,主要是在處理變參宏時避免多餘的逗號。

作用解釋:

在變參宏中,如果你使用 __VA_ARGS__ 並且呼叫宏時沒有傳遞任何可變引數,那麼會出現一個多餘的逗號,導致語法錯誤或不期望的行為。例如:

#define DEBUG_LOG(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)

假設你這樣呼叫宏:

DEBUG_LOG("A message");

展開後會變成:

fprintf(stderr, "A message", );

這會在 fprintf 函式呼叫中留下一個多餘的逗號,導致編譯錯誤。

為了防止這種情況,使用 ##__VA_ARGS__ 來自動去掉這個多餘的逗號。

示例:

#define DEBUG_LOG(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)

__VA_ARGS__ 是空的時候,## 會將前面的逗號自動移除。例如:

  • 有可變引數:

    DEBUG_LOG("Value: %d", 42);
    

    展開後:

    fprintf(stderr, "Value: %d", 42);
    
  • 沒有可變引數:

    DEBUG_LOG("A message");
    

    展開後:

    fprintf(stderr, "A message");
    

在這種情況下,##__VA_ARGS__ 確保即使沒有傳遞可變引數,宏的展開依然是合法的,不會留下多餘的逗號。

總結:

##__VA_ARGS__ 的主要作用是在變參宏中,當 __VA_ARGS__ 為空時,自動去掉前面的逗號,確保宏的展開結果是有效的 C/C++ 程式碼。

注意事項

如果用##來連線字串,那麼要注意:這個連線操作發生在宏展開之前。

相關文章