標準預定義宏 (C89/C99/C11)
| 宏 | 類型 | 含義 | 標準 |
__DATE__ | 字符串常量 | 編譯日期 "Mmm dd yyyy" (如 "Feb 12 1996") | C89 |
__TIME__ | 字符串常量 | 編譯時間 "hh:mm:ss" | C89 |
__FILE__ | 字符串常量 | 當前源文件路徑 | C89 |
__LINE__ | 整數常量 | 當前行號 | C89 |
__func__ | 字符串變量 | 當前函數名 (靜態存儲) | C99 |
__STDC__ | 整數常量 | 1 表示符合標準 C | C89 |
__STDC_VERSION__ | 長整數常量 | 版本號 yyyymmL (199409L= C90, 199901L= C99) | C99 |
__STDC_HOSTED__ | 整數常量 | 1=託管環境(完整庫), 0=自由環境 | C99 |
GCC/Clang 常用擴展宏
| 宏 | 含義 |
__FUNCTION__ | __func__ 同義詞 (GCC 早期引入) |
__PRETTY_FUNCTION__ | 函數簽名 (含參數、模板、類名,C++ 極其有用) |
__BASE_FILE__ | 主源文件名 (遞歸 #include 時頂層文件) |
__COUNTER__ | 遞增整數 (每次使用 +1,生成唯一標識) |
__TIMESTAMP__ | 文件最後修改時間 |
__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__ | GCC 版本號 |
__clang__, __clang_major__... | Clang 版本號 |
__cplusplus | C++ 版本 (199711L, 201103L, 201402L, 201703L, 202002L) |
調試與日誌最佳實踐
// 通用斷言宏
#define ASSERT(cond) \
do { if (!(cond)) { \
fprintf(stderr, "ASSERT failed: %s, %s:%d, %s\n", \
#cond, __FILE__, __LINE__, __func__); \
abort(); \
} } while(0)
// 格式化日誌宏
#define LOG(fmt, ...) \
fprintf(stderr, "[%s:%d %s] " fmt "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
// 使用示例
void process(int fd) {
LOG("start fd=%d", fd);
ASSERT(fd >= 0);
// ...
}
#line 指令交互
#line 100 "virtual.c" // 修改 __LINE__=100, __FILE__="virtual.c"
int x = 1; // __LINE__ 為 101
#line 200 // 僅修改行號
int y = 2; // __LINE__ 為 201
常用於代碼生成工具(lex/yacc、protobuf、Qt MOC)保持錯誤定位準確。
注意事項
__func__ 是變量而非宏,不能用 #ifdef 判斷,但可作為字符串使用。
__STDC__ 在 GCC 非標準模式 (-traditional-cpp) 下可能未定義,檢查用 #if __STDC__ 而非 #ifdef。
- C++ 中
__cplusplus 是檢測標準版本的唯一可靠宏。