2038问题是什么?不知道大家听说过2038问题吗?不管你听说过与否,这篇文章都会告诉你什么是2038问题。Unix时间戳定义为格林威治标准时间1970年1月1日00:00:00(北京时间1970年1月1日08:00:00)到现在的总秒数。在C语言中,常用time_t来表示。例如:#include#includeintmain(void){time_trawtime=10;//time(NULL)获取当前时间戳structtminfo;//转换为tm结构localtime_r(&rawtime,&info);//转换为字符串printf("Timeis:%s\n",asctime(&info));return0;}运行结果:timeis:ThuJan108:00:101970这里我把rawtime设置为10,从打印出来的结果来看,也知道是正确的。(注意,由于我们的时区是东八区,所以得到的时间是八点。)当然这里的内容暂时不展开,主要关注time_t。但实际上time_t是什么?通常,time_t直接或间接定义如下:typedeflongtime_t我们知道,在32位程序下,long占用四个字节的空间:#include#includeintmain(void){printf("longsize:%zd\n",sizeof(long));printf("longmax:%ld\n",LONG_MAX);return0;}编译运行:$gcc-m32-omainmain.c$./main42147483647可以看到对于32位程序,long的最大值为2147483647。溢出引起的问题是指一旦时间戳的值大于四字节的LONG_MAX,time_t将无法正确存储时间戳。比如初始程序编译为32位程序,修改rawtime的值为2147483648,运行结果为(注意溢出的结果是undefined):#include#includeintmain(void){time_trawtime=2147483648;//time(NULL)获取当前时间戳structtminfo;//转换为tm结构localtime_r(&rawtime,&info);//转换为字符串printf("时间是:%s",asctime(&info));return(0);}然后我们编译运行:$gcc-m32-omainmain.cwarning:thisdecimalconstantisunsignedonlyinISOC90[enabledbydefault]$./mainis:SatDec1404:45:521901还有第一次编译时出现警告,原因是time_t不能表示2147483649。我们运行之后,也发现结果超出了我们的预期。原来是1901年的时间!2038问题,这和2038有什么关系?编译成64位程序,我们再运行一??下。会发现区间是:TueJan1911:14:082038。这个4字节整数表示的时间戳值最多只能表示北京时间2038年1月19日11:14:07。一旦达到此时间,这些32位程序可能会出现错误行为,因为它们无法将时间正确识别为2038,并且可能会跳回1970或1901,具体取决于实施方式。综上所述,你一定很清楚。在32位程序中,time_t的最大值为2147483647,即最多到北京时间2038年1月19日11:14:07,之后会出现异常。但是,如果使用64位整数,则可以记录到大约2900亿年后的12月4日星期日15:30:08(UTC)292,277,026,596。当然,如果使用无符号整数,这个错误会推迟到2106年,那时候还会有32位的程序运行吗?2038问题只是一个介绍。事实上,程序中有很多问题现在不会溢出,但将来可能会溢出。你会关注吗?