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

C語言宏定義進階技巧:符號連接##、字符串化#、字符常量#@、屏蔽未用參數警告

     編輯:關於C語言

三大特殊宏操作符

操作符名稱作用示例(x=1)展開結果
##Token Pasting(符號連接)將兩個標記合併為一個標記#define A(x) T_##xA(1) → T_1
#Stringification(字符串化)將參數轉為字符串字面量#define C(x) #xC(1) → "1"
#@Charizing(字符常量化,GCC擴展)將參數轉為字符常量#define B(x) #@xB(1) → '1'

實戰場景 1:自動生成變量名/函數名

#define DECLARE_VAR(type, name) type var_##name
#define GETTER(type, name) type get_##name() { return var_##name; }

DECLARE_VAR(int, count);   // 展開: int var_count;
GETTER(int, count);        // 展開: int get_count() { return var_count; }

實戰場景 2:調試打印宏——字符串化變量名與值


#define DEBUG_PRINT(fmt, val) \
    printf("File %s Line %d: " #val " = " fmt "\n", __FILE__, __LINE__, val)

int x = 42;
DEBUG_PRINT("%d", x);
// 輸出: File main.c Line 10: x = 42

實戰場景 3:屏蔽「未使用參數」編譯警告


#define UNUSED_PARAM(p) ((void)(p))

void callback(int fd, int events, void* arg) {
    UNUSED_PARAM(fd);
    UNUSED_PARAM(events);
    // 只使用 arg,不觸發 -Wunused-parameter 警告
}

原理:(void)expr 明確告訴編譯器「我故意忽略此表達式的值」,屬標準 C 語法,跨編譯器兼容。

進階組合:可變參數宏 + 字符串化


#define LOG(fmt, ...) printf("[%s:%d] " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__)

LOG("User %s login from %s", "admin", "192.168.1.1");
// 輸出: [main.c:20] User admin login from 192.168.1.1

避坑指南

  • #@ 為 GCC 擴展,**非標準 C**,MSVC 不支援,跨平台項目慎用。
  • ## 兩側需有標記,#define PASTE(a,b) a##b 若調用 PASTE(,var) 會報錯。
  • 宏參數帶副作用(如 MACRO(i++))可能多次求值,嚴禁在宏中直接使用有副作用的表達式。
  • 頭文件防衛宏仍是 #ifndef __HEADER_H__ 模式最通用,#pragma once 雖簡潔但非標準。

總結

宏三大操作符 ##、#、#@ 分別解決「標記拼接」「變量名轉字符串」「變量名轉字符常量」三類元編程需求。配合 __VA_ARGS__、__FILE__、__LINE__,能構建極具表達力的調試、日誌、代碼生成工具集。**宏無類型檢查、無作用域、難調試**,核心邏輯論盡量用 inline 函數/模板替代,宏專注於「語法層面的代碼生成」。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved