【发布时间】:2011-05-27 19:56:33
【问题描述】:
我注意到一些程序员将 unsigned long 用于 timeval 的 tv_sec 和 tv_usec [当他们复制或操作它们时],而它们被定义为简单的 long。
虽然这确实让我想知道为什么当时间通常向前时它们会被这样定义。
【问题讨论】:
标签: c unix time unsigned timeval
我注意到一些程序员将 unsigned long 用于 timeval 的 tv_sec 和 tv_usec [当他们复制或操作它们时],而它们被定义为简单的 long。
虽然这确实让我想知道为什么当时间通常向前时它们会被这样定义。
【问题讨论】:
标签: c unix time unsigned timeval
对这些变量使用long int 将一直有效,直到year 2038,之后tv_sec 将在long 为4 字节的机器上溢出。
The <sys/time.h> header shall define the timeval structure that includes at least the following members:
time_t tv_sec Seconds.
suseconds_t tv_usec Microseconds.
您应该注意到time_t 类型被使用而不是long,但在某些系统上它也是 32 位表示,而在其他系统上甚至有 64 位表示。为了避免溢出,time_t 可能会被更改为无符号的 32 位整数或 64 位整数。
这就是为什么有些人使用unsigned long,因为它会阻止溢出直到 2100+ 年。您应该改用time_t 类型,并且您无需考虑您的程序将来应该运行多长时间。
【讨论】:
long,问题就会消失。
time_t 在所有 Unix 系统上都是 long,在 64 位 Unix 系统上是 64 位宽,所以它在实践中永远不会溢出。
time_t 是 long。可能是long long。遗憾的是,对于大多数人来说,二进制软件兼容性比修复遗留限制更重要,因此在实践中,我们在 32 位机器上坚持使用 32 位 time_t。
当 unix 时间被发明时,负时间可能是有意义的。就像,AT&T 需要足够的时间戳来记录 1960 年代发生的事情。
至于微秒,如果你减去两个值,你可以用带符号的值变成负数,用无符号的值变成 4+十亿。与 0 相比似乎更直观。
【讨论】:
(time_t)-1 一直是一个错误指示器,在这种情况下,使用负时间值似乎是可疑的......
tv_sec 的类型为 time_t。 tv_usec 的类型为 long,并且需要签名,因为在减去 timeval 值以计算时间间隔时,您将(平均 50% 的时间)在 tv_usec 中得到否定结果,并且您必须检测到这一点并将其转换为来自tv_sec 字段的借用。标准 (POSIX) 可以改为将类型设置为无符号并要求您提前检测包装,但它没有,可能是因为这将更难使用并且与现有做法相矛盾。
在范围方面,tv_usec 也没有理由是无符号的,因为它真正需要能够表示的最大范围是 -999999 到 1999998(或者如果您想累积多个加法,则为数倍/重整化之前的减法)。
【讨论】: