#include <stdio.h>
#define PRINT_CLINE() printf("%d", ______)
int main(void) {
PRINT_CLINE();
PRINT_CLINE();
return 0;
}
請在橫線處填代碼,使輸出為 34。答案揭曉在文末。
#define PI 3.14159
預處理階段將所有 PI 替換為 3.14159。無參數、無類型檢查,純文本替換。
#define MAX(a, b) ((a) > (b) ? (a) : (b))
關鍵點:參數兩側必須加括號,防止邊際效應。如 MAX(x+y, z) 若無內層括號會展開為 x+y > z ? x+y : z,優先級錯誤。
#@ (非標準,部分編譯器支持)#define PT_CHAR(x) printf("%c", #@x)
PT_CHAR(d); // 展開為 printf("%c", 'd'); 輸出 d
將參數轉為字符字面量。標準 C 中不存在 #@,標準做法見下文。
##define PT_STR(x) printf("%s", #x)
PT_STR(Hello!); // 展開為 printf("%s", "Hello!");
將參數轉為字符串字面量,自動添加雙引號並轉義內部引號。
###define PRINT_SYM(n) printf("symbol" #n "=%d", symbol##n)
int symbol9 = 9;
PRINT_SYM(9); // symbol9=9
## 將兩側 Token 連接成單一 Token。此處 symbol##9 → symbol9。
| 宏 | 含義 |
|---|---|
__LINE__ | 當前源代碼行號 (int) |
__FILE__ | 當前源文件名 (字符串) |
__DATE__ | 編譯日期 "Mmm dd yyyy" (字符串) |
__TIME__ | 編譯時間 "hh:mm:ss" (字符串) |
__STDC__ | 嚴格遵循 ANSI C 時為 1 |
__cplusplus | C++ 編譯時定義 |
利用 __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++ 應盡量以語言級特性替代。