gettimeofday取毫秒的溢出问题

游戏最近上线,在de一系列bug。其中有个bug比较有意思,是碰撞攻击Boss时,第一下总是打了不算。因为攻击Boss加了50ms的无敌间隔,以防止Boss在短时间连续碰撞中被秒杀。

遂怀疑是取系统时间出了问题,但在Mac上调试,发现输出完全无误。直到连上了iPhone5进行真机调试时,发现获取系统时间的函数输出的是一个负数。

以下是取当前系统的毫秒数。

inline long getCurrentTime()
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}

出现此问题,显然是溢出了。由于tv.tv_sec的类型是long,而long在32位的机器上的范围为−2,147,483,648 -> 2,147,483,647

因为Mac运行的是64位的架构,而iPhone5是32位的架构,所以在Mac上没问题,而在iPhone5就出现问题了。

tv.tv_sec表示是Unix时间戳。写下本文时的unix时间戳为1425312506,乘1000后显然是溢出了。

解决方案很简单,用long long就行了。(读者注:在不支持long long类型的编译器上可以使用double类型。)

inline long long getCurrentTime()
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    long long ms = tv.tv_sec;
    return ms * 1000 + tv.tv_usec / 1000;
}

解决完这个bug,不禁想到当unix时间戳到了2,147,483,647会是怎么办。这个问题早就有人考虑到了,叫做2038年问题

也就是到了2038年1月19日3时14分07秒后,如果在32位设备上用long类型再表示unix时间戳就溢出了。。

image

第一行是“time_t”数字的二进制表示;第二行是其十进制表示;第三行是受影响的计算机理解的时间;第四行是实际的时间

不过到了2038年,还有32位设备么。。。

关注微信公众号:timind

2 responses

  1. 楼主,也可以把ms定义为double类型,long long 类型有些编译器可能不支持,在VC中也可以用__int64类型

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注