strptime解析01/01/0000出现歧义结果的原因及疑问
关于strptime解析
01/01/0000的行为疑问 问题背景
在C++代码中解析日期字符串01/01/0000时,不同环境下运行结果存在差异:
- 本地Linux机器(GCC 4.8.5)编译运行后输出:
0-1-1 0:0 - 在cpp.sh平台运行相同代码,输出为:
1900-1-1 0:0
疑问
- 在strptime的实现中,解析
01/01/0000属于未定义行为吗? - 是否存在某些机器环境下,strptime会返回
nullptr的情况?
本地测试代码及环境信息
编译运行命令及输出
[genstor@bharath cpp]$ g++ -std=c++11 test.cpp -o test.out [genstor@bharath cpp]$ ./test.out 0-1-1 0:0
测试代码
#include <iostream> #include <sstream> #include <ctime> int main() { struct tm tm{}; std::string s("01/01/0000"); if (strptime(s.c_str(), "%d/%m/%Y", &tm)) { int d = tm.tm_mday, m = tm.tm_mon + 1, y = tm.tm_year + 1900; std::cout << y << "-" << m << "-" << d << " " << tm.tm_hour << ":" << tm.tm_min; } }
GCC版本信息
[genstor@bharath cpp]$ g++ -v Using built-in specs. COLLECT_GCC=g++ COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/lto-wrapper Target: x86_64-redhat-linux Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux Thread model: posix gcc version 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC)
解答
1. 解析01/01/0000是否属于未定义行为?
POSIX标准对strptime的%Y格式说明是解析4位十进制年份,但标准并未明确规定年份为0000时的行为。不同的C库实现(比如GNU libc和musl libc)对年份下限的处理存在差异:
- GNU libc的早期版本(如你使用的GCC 4.8.5配套的libc)允许年份为0,解析后
tm_year字段会被设为0 - 1900 = -1900,因此输出0-1-1; - 部分实现(如cpp.sh使用的库)会将
0000视为无效年份,自动映射到1900(即tm_year=0),所以输出1900-1-1。
这种差异属于实现定义行为而非严格意义上的未定义行为——各实现会有明确的处理逻辑,但标准未统一规定,因此不同环境结果不同。
2. 是否存在环境会让strptime返回nullptr?
是的。当strptime无法解析输入字符串时会返回nullptr,针对01/01/0000这种情况:
- 部分严格遵循年份范围限制的C库实现(如某些嵌入式系统的库,或配置了严格日期校验的版本)会将
0000判定为无效年份,此时strptime会返回nullptr,不会填充tm结构体; - 若输入字符串格式与指定的
%d/%m/%Y不匹配(比如日期或月份超出合理范围),也会返回nullptr,但这里格式匹配,仅年份值的有效性由实现决定。
内容的提问来源于stack exchange,提问作者Bharath Mourya
相关产品推荐
相关产品推荐

