strftime必须传入struct tm*指针,不能直接用time_t;需先调用localtime_r(POSIX)或localtime_s(Windows)转换,再检查返回值防缓冲区溢出。

strftime 函数的基本调用方式和必需参数
strftime 是 C 标准库中把 struct tm * 转成格式化字符串的唯一可靠函数,但它**不接受 time_t 直接输入**。必须先用 localtime 或 gmtime 转成 struct tm,否则会编译通过但运行时崩溃或输出乱码。
常见错误写法:strftime(buf, sizeof(buf), "%Y-%m-%d", time_ptr) —— 这里 time_ptr 若是 time_t * 类型,类型不匹配,行为未定义。
- 第一步永远是:
struct tm *tm_ptr = localtime(&t)(注意取地址符&) - 第二步才调用:
strftime(buf, sizeof(buf), "%H:%M:%S", tm_ptr) -
buf必须是可写的字符数组(不能是字面量字符串),且大小要留足空间(比如 64 字节通常够用) - 返回值是实际写入的字符数(不含结尾
\0),为 0 表示缓冲区太小或格式非法
常用格式符与中文环境下的陷阱
Windows 和 Linux 下 strftime 对中文 locale 的支持差异极大。比如 %A(星期全名)、%B(月份全名)在 Linux 上设好 setlocale(LC_TIME, "zh_CN.UTF-8") 后能正常输出“星期一”“十二月”,但在 Windows 的 MSVC 中即使设了 "Chinese_China.936",也大概率返回空字符串或问号。
- 稳妥做法:避免依赖
%A/%B输出中文,改用查表映射(如weekdays[tm->tm_wday]) -
%c是“本地日期时间格式”,但各平台实现不同:Linux 可能是 “2024年12月01日 星期日 15:30:45”,Windows 可能是 “12/01/2024 15:30:45” —— 别把它当跨平台方案 -
%z(UTC 偏移)在 Windows 上不可用,MSVC 编译会忽略;GCC/Clang 支持,但输出如+0800,不是+08:00 - 想输出毫秒?
strftime不支持。得手动拼接:snprintf+tv.tv_usec / 1000
线程安全与替代方案提醒
localtime 返回的是静态缓冲区指针,**不是线程安全的**。多线程环境下并发调用会导致数据被覆盖,看似随机出错(比如时间突然跳回 1970 年)。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
立即学习“C++免费学习笔记(深入)”;
- POSIX 系统优先用
localtime_r(&t, &tm)(带_r后缀),tm是你自己的栈变量 - Windows 没有
localtime_r,可用localtime_s(&tm, &t)(需定义_CRT_SECURE_NO_WARNINGS或用安全版本) - C++20 起推荐用
std::format("{:%Y-%m-%d %H:%M:%S}", std::chrono::system_clock::from_time_t(t)),但目前 MSVC 2022 v17.8+、GCC 13+ 才较稳定,旧项目慎用 - 别用
ctime替代 —— 它只能输出固定格式,且同样非线程安全
一个最小可运行示例(含错误检查)
下面这段代码在 Linux 和 Windows(MSVC)下都可通过编译并正确输出:
#include <ctime>
#include <iostream>
#include <cstring>
int main() {
time_t t = std::time(nullptr);
struct tm tm_buf;
#ifdef _WIN32
localtime_s(&tm_buf, &t);
#else
localtime_r(&t, &tm_buf);
#endif
char buf[64];
if (strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm_buf) == 0) {
std::cerr << "strftime failed: buffer too small or invalid format\n";
return 1;
}
std::cout << buf << "\n";
}
注意 strftime 的返回值检查容易被跳过,但缓冲区溢出风险真实存在 —— 尤其当你动态拼接格式串时,长度估算稍有偏差就会截断。

















