__DATE__ 和 __TIME__ 是编译时字符串字面量,不可加括号调用;正确用法是 "Build: "__DATE__" "__TIME__,依赖字面量自动拼接,适用于 const char* 日志接口。

__DATE__ 和 __TIME__ 不是函数,别加括号调用
直接写 __DATE__ 和 __TIME__ 就行,它们是编译时展开的字符串字面量,不是运行时可调用的东西。加括号会报错,比如 __DATE__() 或 __TIME__() 是非法语法。
正确拼接方式依赖 C++ 字符串字面量自动连接规则:
-
"Build: "__DATE__" "__TIME__—— 中间不能有分号、逗号或空格打断连接 - 如果日志接口接受
const char*(如多数 C 风格日志宏),直接传入即可,无需std::string转换 - 若用在
std::cout 或其他流操作中,需显式转为 <code>std::string或用std::string_view包裹,否则可能触发隐式转换失败
__DATE__ 格式含前导空格,解析时容易出错
__DATE__ 固定输出为 "Mmm DD YYYY" 格式,其中 DD 是“带前导空格”的两位数(如 "Jul 7 2026",注意 7 前有两个空格),不是零填充。这会让 sscanf 或字符串分割逻辑意外失败。
- 用
sscanf(__DATE__, "%s %d %d", month, &day, &year)时,%d会跳过前导空格,但若后续逻辑依赖固定宽度字段(如 substr(4,2) 取日期),就会越界 - 想安全提取年份?推荐用
__DATE__ + 7指针偏移(因年份总在最后 4 字符),或用std::string(__DATE__).substr(7) -
__TIME__倒是干净:"HH:MM:SS",但注意它反映的是编译机本地时钟,不是 UTC
CI/CD 环境下时区不一致会导致时间戳混乱
流水线不同节点(如 macOS builder、Ubuntu runner、Windows agent)若未统一时区,__TIME__ 输出可能相差数小时,同一 commit 编译出多个“不同时间戳”的二进制,干扰版本追踪和问题复现。
立即学习“C++免费学习笔记(深入)”;
- 最稳妥做法:构建脚本注入(如 CMake 中用
configure_file+$<configure_time></configure_time>或execute_process调用date -u +%Y-%m-%dT%H:%M:%SZ) - 若坚持用宏,所有构建机必须设为 UTC:
sudo timedatectl set-timezone UTC - 别信
__TIME__的“精确性”——它只精确到秒,且受编译器启动延迟影响,不适合做性能基准
增量构建和缓存失效风险常被忽略
__DATE__ 和 __TIME__ 每次编译都变,会导致目标文件哈希值改变,破坏 ccache、Ninja 的增量构建,甚至让 Docker 构建层失效。
- 开发阶段可用,但发布构建建议禁用:用
#ifdef BUILD_RELEASE包裹,或改用 Git commit 时间(git log -1 --format=%cd --date=iso注入) - 头文件里定义版本字符串时,避免把
__DATE__放进频繁包含的公共头,否则整个项目重编译 - 静态库中嵌入这些宏,会导致链接时无法 deduplicate 目标文件——即使源码完全相同,只要编译时间不同,符号就不同


















