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

C語言宏定義進階技巧全解析:從基礎替換到標準預定義宏

     編輯:關於C

引子:一道經典面試題

#include <stdio.h>

#define PRINT_CLINE() printf("%d", ______)

int main(void) {
    PRINT_CLINE();
    PRINT_CLINE();
    return 0;
}

請在橫線處填代碼,使輸出為 34。答案揭曉在文末。


宏定義六大核心用法

1. 簡單替換

#define PI 3.14159

預處理階段將所有 PI 替換為 3.14159。無參數、無類型檢查,純文本替換。

2. 帶參數宏

#define MAX(a, b) ((a) > (b) ? (a) : (b))

關鍵點:參數兩側必須加括號,防止邊際效應。如 MAX(x+y, z) 若無內層括號會展開為 x+y > z ? x+y : z,優先級錯誤。

3. 字符化運算符 #@ (非標準,部分編譯器支持)

#define PT_CHAR(x) printf("%c", #@x)
PT_CHAR(d); // 展開為 printf("%c", 'd'); 輸出 d

將參數轉為字符字面量。標準 C 中不存在 #@,標準做法見下文。

4. 字符串化運算符 #

#define PT_STR(x) printf("%s", #x)
PT_STR(Hello!); // 展開為 printf("%s", "Hello!");

將參數轉為字符串字面量,自動添加雙引號並轉義內部引號。

5. 連接運算符 ##

#define PRINT_SYM(n) printf("symbol" #n "=%d", symbol##n)
int symbol9 = 9;
PRINT_SYM(9); // symbol9=9

## 將兩側 Token 連接成單一 Token。此處 symbol##9 → symbol9。

6. ANSI C 標準預定義宏

宏含義
__LINE__當前源代碼行號 (int)
__FILE__當前源文件名 (字符串)
__DATE__編譯日期 "Mmm dd yyyy" (字符串)
__TIME__編譯時間 "hh:mm:ss" (字符串)
__STDC__嚴格遵循 ANSI C 時為 1
__cplusplusC++ 編譯時定義

面試題答案揭曉

利用 __LINE__ 宏獲取當前行號。第一次調用在行 7,第二次在行 8。為輸出 34,需輸出行號 3 和 4,故定義:

#define PRINT_CLINE() printf("%d", __LINE__ - 4)

假設宏定義在行 3,則 __LINE__ - 4 在行 7 為 3,行 8 為 4,拼接輸出 34。


最佳實踐建議

  • 宏參數、整體表達式**務必加括號**。
  • 避免在宏中使用有副作用的表達式(如 i++),因多次展開會多次求值。
  • 優先使用 const、inline 函數、模板 替代宏,類型安全且可調試。
  • 善用 __FILE__, __LINE__ 實現調試日誌、斷言宏。

總結

宏是 C 語言預處理器的強大工具,掌握 #, ##, 預定義宏等進階特性,能編寫靈活的元編程代碼。但「宏無類型、無作用域、難調試」,務必謹慎使用,現代 C/C++ 應盡量以語言級特性替代。

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