c++oding="utf-8" ?>
多线程环境下必须用localtime_r(posix)或localtime_s(windows),因localtime返回指向静态缓冲区的指针,多线程调用会相互覆盖导致数据错误。

time_t 转 struct tm 用 localtime_r 还是 localtime?
多线程环境下直接用 localtime 是危险的——它返回指向静态缓冲区的指针,多个线程调用会相互覆盖。必须用线程安全版本 localtime_r(POSIX)或 localtime_s(Windows)。Linux/macOS 下优先选 localtime_r,传入你自己的 struct tm 缓冲区地址:
struct tm tm_buf;
if (localtime_r(×tamp, &tm_buf) == nullptr) {
// 处理错误:timestamp 可能超出 time_t 有效范围(如负值或过大)
}
注意:localtime_r 返回 struct tm*,成功时等于你传入的地址,失败返回 nullptr,别忽略这个判断。
格式化字符串里 %Y 和 %y 到底差在哪?
%Y 输出 4 位年份(如 2024),%y 输出 2 位(如 24)。很多 bug 来自混淆这两者——比如日志归档按年份分目录,用 %y 会导致 2024 和 2124 都写进 24/ 目录。常用组合建议:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
-
"%Y-%m-%d %H:%M:%S"→"2024-05-21 14:30:45" -
"%Y%m%d_%H%M%S"→"20240521_143045"(适合文件名) - 避免
%D(等价于%m/%d/%y),年份两位数易歧义
strftime 缓冲区大小设多少才不溢出?
strftime 不自动分配内存,靠你传入的缓冲区长度防截断。最短安全长度取决于格式串最大可能输出长度。例如 "%Y-%m-%d %H:%M:%S" 最长 19 字符(加结尾 \0 共 20),但保险起见建议最小设 64;若含时区、微秒等扩展字段,至少 128。关键点:
- 务必检查返回值:
size_t ret = strftime(buf, sizeof(buf), fmt, &tm_buf);,若ret == 0表示缓冲区不够或格式串非法 - 不要传
sizeof(char*)这类错误大小 - Windows 下
strftime对中文 locale 支持不稳定,建议固定用"C"locale
需要毫秒级时间戳怎么办?
time_t 通常是秒级,要毫秒得用 std::chrono。C++11 后推荐路径:先转 std::chrono::system_clock::time_point,再拆解。注意两点:
-
std::chrono::system_clock::to_time_t(tp)只取秒部分,毫秒丢失;需手动提取:auto ms = std::chrono::duration_cast<:chrono::milliseconds>(tp.time_since_epoch()).count() % 1000;</:chrono::milliseconds> - 跨平台时,
std::put_time在旧版 libstdc++(如 GCC 7 前)不支持,fallback 用strftime更稳 - 若只需“带毫秒的字符串”,常见做法是先用
strftime格式化到秒,再拼接printf("%03d", ms)
真正难的不是转换本身,而是时区处理和跨平台 locale 行为差异——比如 macOS 的 setlocale(LC_TIME, "zh_CN.UTF-8") 可能让 %A 输出中文星期,但 Linux 上未必生效。这类细节不测到具体环境很难绕开。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










