什么是什问题2038问题
不知道你有没有听过2038问题?无论你是否听过,本文将带你认识什么是什问题2038问题。

Unix时间戳
定义为从格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的什问题总秒数。而在C语言中,什问题常用time_t来表示。什问题举个例子:
#include <stdio.h> #include <time.h> int main (void) { time_t rawtime = 10;//time(NULL)获取当前时间戳 struct tm info; //转为tm结构 localtime_r( &rawtime,什问题&info); //转为字符串 printf("时间为: %sn", asctime(&info)); return 0; }运行结果:
时间为: Thu Jan 1 08:00:10 1970在这里,我给rawtime设置为10,什问题从打印结果来看也知道是什问题正确的了。(注意,什问题由于我们的什问题时区为东八区,所以得到的什问题时间是八点。)
当然这里的什问题内容暂时不展开,主要关注time_t。什问题
然而实际上,什问题time_t到底是什问题什么?
通常,time_t直接或者间接被定义为下面这样:
typedef long time_t我们知道,在32位程序下面,IT技术网long占用四个字节空间:
#include<stdio.h> #include <limits.h> int main(void) { printf("long size:%zdn",sizeof(long)); printf("long max:%ldn",LONG_MAX); return 0; }编译运行:
$ gcc -m32 -o main main.c $ ./main 4 2147483647可以看到,对于32位程序而言,long的最大值为2147483647。
溢出引发的问题
也就是说,一旦时间戳的值大于四字节的LONG_MAX,time_t将会无法正确存储这个时间戳。
举例来说,最开始的程序编译为32位程序,修改rawtime的值为2147483648,运行结果为(注意,溢出的结果是未定义的):
#include <stdio.h> #include <time.h> int main (void) { time_t rawtime = 2147483648;//time(NULL)获取当前时间戳 struct tm info; //转为tm结构 localtime_r( &rawtime,&info); //转为字符串 printf("时间为: %s", asctime(&info)); return(0); }然后我们编译运行:
$ gcc -m32 -o main main.c warning: this decimal constant is unsigned only in ISO C90 [enabled by default] $ ./main 间为: Sat Dec 14 04:45:52 1901首先编译的时候也有警告,原因在于2147483649无法使用time_t来表示,我们运行之后,也发现结果出乎我们的意料,它竟然是一个1901年的云服务器提供商时间!
2038问题
那这和2038有什么关系呢?
编译为64位程序我们再次运行就会发现:
间为: Tue Jan 19 11:14:08 2038这个4字节整型表示的时间戳值只能表示到北京时间2038年1月19日11时14分07秒,一旦到了这时间之后,这些32位程序就可能运行异常,因为它们无法将此时间正确的识别为2038年,而可能会依个别实现而跳回1970年或1901年。
总结
到此,想必你已经很清楚了。由于在32位程序中,time_t最大值为2147483647,即最多表示到北京时间2038年1月19日11时14分07秒,因此在此之后就会出现异常。
而如果使用64位整型,则可以记录至约2900亿年后的292,277,026,596年12月4日15:30:08,星期日(UTC)。
当然,如果采用无符号整型,这个错误会被延后到 2106 年。到那时,还会有32位的程序在运行吗?
2038问题只是一个引子,实际上在程序中有很多现在不会溢出而将来可能溢出的问题,你会关注吗?
源码下载



