《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++生态系统的重要组成部分,合理使用可以显著提升代码的可调试性和可维护性。