根据我的理解,time_t rawtime = 0xffFFffFF
是GMT: Sunday, February 7, 2106 6:28:15 AM
但是下面的程序在一些编译器中会带来Thu 1970-01-01 02:59:59 MSK
,而在其他编译器中会崩溃。
int main()
{
time_t rawtime = 0xffFFffFF;
struct tm ts;
char buf[80];
ts = *localtime(&rawtime);
strftime(buf, sizeof(buf), "%a %Y-%m-%d %H:%M:%S %Z", &ts);
printf("%sn", buf);
return 0;
}
rawtime >0x7fFFffFF
。为什么?如何解决这个问题?
乌利希期刊指南:我需要有一系列的警报,并在时间到来时采取行动。这是嵌入式系统,我不能为复杂的数据类型浪费内存和资源。
在大多数平台上,time_t
类型是一个有符号整数。在大多数平台上,time_t
从1970年1月1日开始计算时间。结合这两个事实,我们有负的time_t
值对应于 1970年1月1日之前的日期。
如果机器上的time_t
是有符号32位整数,则0xffffffff
为-1。因此,从理论上讲,该值对应于1969年12月31日的UTC时间23:59:59,即UTC午夜前一秒。但在某些上下文中,-1表示错误。因此,尽管我从未遇到过它,但如果有localtime()
实现将输入的值-1视为错误,我并不完全感到惊讶。
你说它"崩溃了",但那有一部分是你的错。localtime
通过返回空指针表示失败。所以写
struct tm *ts;
ts = localtime(&rawtime);
if(ts == NULL) {
fprintf(stderr, "localtime failedn");
exit(1);
}
strftime(buf, sizeof(buf), "%a %Y-%m-%d %H:%M:%S %Z", ts);
如果time_t
是一个带符号的32位值,它的最大值是2147483647(仍然假设Unix纪元为1970),对应于2038年1月19日03:14:07 UTC。最小值2147483648对应于1901年12月13日20:45:52 UTC。
你是对的,如果time_t
被视为无符号,最大32位值将是4294967295,并对应于你提到的2106年的日期和时间。
如果time_t
是64位类型,这是越来越流行的(为了防止y2.038k问题或多或少是必要的),最大值是如此之大,以至于它实际上毫无意义。(它太大了,以至于年份甚至不能用32位来表示。)
最后,值得记住的是time_t
的解释是特定于平台的。从理论上讲,它不需要计算秒数,也不需要从1970年1月1日算起,甚至不需要是个整数。即使这些事实成立,也没有规则说time_t
必须有签名,所以在一个为广泛可移植性而设计的程序中,我不会指望有对应于1901-1970的值,因为在某些平台上它们可能对应于2038-2106,毕竟。
time_t
的类型和范围是由实现定义的,没有最低要求。它可以是有符号的、无符号的、32位的、64位的、浮点的等等。
如果你正在使用的编译器没有一个time_t
的范围满足你的要求,你可以:
- 使用不同的编译器,或者
- 避免使用
time_t
或 - 重新构建你的程序,使其在编译器的
time_t
限制内工作。
正如在注释中提到的,很可能是由于localtime
由于超出范围的输入而返回空指针,并且您在没有首先检查null的情况下解引用它。