《C/C++预定义宏深度剖析:编译上下文获取指南》
1. __FILE__ - 当前文件名
 
作用:展开为当前源文件的绝对路径或相对路径字符串
 类型:字符串常量(const char[])
 典型用途:错误报告、调试日志
printf("Current file: %s\n", __FILE__); 
// 输出示例: Current file: /project/src/main.cpp
 
注意:
- 路径格式取决于编译器(可能是绝对路径或相对路径)
 - C++17起可用
__FILE_NAME__仅获取文件名部分(非标准但Clang/GCC支持) 
2. __LINE__ - 当前行号
 
作用:展开为当前代码行的十进制整数
 类型:整型常量
 典型用途:错误定位、断言宏
cout << "Error at line " << __LINE__ << endl;
// 输出示例: Error at line 42
 
特殊用法:
#define LOG(msg) \cout << __FILE__ << ":" << __LINE__ << " - " << msg << endl
 
3. __DATE__ - 编译日期
 
作用:展开为编译开始的日期字符串
 格式:"MMM DD YYYY"(例如"Jun 30 2023")
 类型:字符串常量
 典型用途:版本信息、构建时间戳
cout << "Build date: " << __DATE__ << endl;
// 输出示例: Build date: Apr 15 2024
 
注意:
- 月份缩写为英文3字母(Jan-Dec)
 - 日期不足两位时用空格填充(如
"Jun 3 2023") 
4. __TIME__ - 编译时间
 
作用:展开为编译开始的时间字符串
 格式:"HH:MM:SS"(24小时制)
 类型:字符串常量
 典型用途:与__DATE__配合记录完整构建时间
cout << "Build time: " << __TIME__ << endl;
// 输出示例: Build time: 14:30:15
 
注意:
- 时间基于编译器所在时区
 - 与文件修改时间无关,仅反映编译时刻
 
5. __func__ - 当前函数名
 
作用:展开为当前函数的未限定名称(unqualified name)
 标准:C99/C++11引入
 类型:静态字符数组(static const char[])
 典型用途:调试日志、异常处理
void foo() {cout << "Inside function: " << __func__ << endl;
}
// 输出: Inside function: foo
 
关键特性:
- 在函数作用域内有效
 - 返回的是函数名而非签名(不包含参数和返回类型)
 - C++11后更推荐使用
__FUNCTION__(同义)或__PRETTY_FUNCTION__(扩展格式) 
组合使用示例
调试日志宏
#define DEBUG_LOG(msg) \do { \fprintf(stderr, "[%s %s] %s:%d (%s) - %s\n", \__DATE__, __TIME__, __FILE__, __LINE__, __func__, msg); \} while(0)// 使用示例
void test() {DEBUG_LOG("Memory allocation failed");
}
/* 输出示例:
[Apr 15 2024 14:30:15] src/main.cpp:45 (test) - Memory allocation failed
*/
 
版本信息头文件
// version.h
#pragma once
#define BUILD_VERSION "1.0.0"
#define BUILD_INFO \"Version: " BUILD_VERSION "\n" \"Built on: " __DATE__ " at " __TIME__ "\n" \"Compiler: " __VERSION__// 使用示例
cout << BUILD_INFO << endl;
/* 输出示例:
Version: 1.0.0
Built on: Apr 15 2024 at 14:30:15
Compiler: g++ 11.2.0
*/
 
注意事项
-  
标准差异:
__func__在C99/C++11前不可用__FUNCTION__和__PRETTY_FUNCTION__是编译器扩展__VERSION__显示编译器版本(非标准但广泛支持)
 -  
运行时行为:
- 所有宏在预处理阶段展开
 __FILE__和__LINE__受#line指令影响
 -  
性能影响:
- 字符串常量不会带来运行时开销
 - 频繁调用时建议用宏而非函数封装
 
 -  
替代方案:
- C++20引入
std::source_location替代部分功能 
#include <source_location> void log(const std::source_location loc = std::source_location::current()) {cout << loc.file_name() << ":" << loc.line() << endl; } - C++20引入
 
这些预定义宏是C/C++生态系统的重要组成部分,合理使用可以显著提升代码的可调试性和可维护性。
