【问题标题】:ctime returning nullctime 返回 null
【发布时间】:2011-08-27 11:01:48
【问题描述】:

如果用户类型time_t被定义为__darwin_time_t,在MacOS X中它本身被定义为long,为什么下面的代码输出8 Time is (null)?也许这有点傻,但我真的无法理解。

#include <stdio.h>
#include <time.h>

int main(void)
{
    time_t time = 0x7FFFFFFFFFFFFFFF;

    printf("%lu\n"
           "Time is %s\n", sizeof(time_t), ctime(&time));

    return 0;
}

【问题讨论】:

  • 我的意思是__darwin_time_t,不是__darwin_time,抱歉。

标签: c macos time x86-64 ctime


【解决方案1】:

时间 0x7FFFFFFFFFFFFFFF 似乎在公元 292,471,210,647 年左右,这无疑会导致 ctime 超过 C99 所保证的 26 个字符,因此它返回 NULL 而不是溢出其缓冲区。一般来说,尽量避免在 Morlocks 与 Eloi 开战之后发生的任何日期。

【讨论】:

  • 嗯,我们的想法是找出time_t 的环绕声何时出现。 Unix 时间的 0x7FFFFFFF 将在 2038 年发生,所以我想我们需要一个新的标准才能在我们的银河系中开始经常发生星际战争。
  • 改用 strftime。或者只检查 localtime 或 gmtime 的 tm_year。
【解决方案2】:

在阅读“专家 C 编程”一书时,我在 Lion 10.7.3 中遇到了同样的问题——t=0xf0c00000000000ctime(&amp;t) 产生 Wed Mar 1 21:07:12 214739252t=0xf0d00000000000, ctime(&amp;t) 返回空指针 (0x0 )。 所以它似乎不是 t 的环绕,而是 ctime(&amp;t) 内部的一些测试,如果 t 太大,则返回空指针。

【讨论】:

  • 只是做了同样的事情。好笑。
【解决方案3】:

来自glibc's implementation 我们读到:

我们限制了可以打印的年份的大小。使用 %d 使用的格式说明符加上 1900 会溢出 number 并打印一个负值。对于某些架构,我们 理论上可以使用 %ld 或更大的整数格式,但是 这意味着输出需要更多空间。这不会是一个 如果'asctime_r'接口被合理定义并且 将传递一个缓冲区大小。

运行下面的程序以找到您机器上的确切限制。

#include <limits.h>
#include <stdio.h>
#include <time.h>

/**
 * Find the largest time_t for which ctime returns a non-NULL value
 * using a bsearch between 0 and LONG_MAX.
 **/
static time_t ctime_max() {
    time_t start = 0, end = LONG_MAX, mid;
    while (start < end) {
        mid = start + (end - start) / 2;
        if (ctime(&mid)) {
            /* this mid is ctime-able; try higher */
            start = mid + 1;
        } else {
            /* this mid is not ctime-able; try lower */
            end = mid;
        }
    }
    /* mid is now the lowest number that's too high; subtract one */
    return mid - 1;
}

int main() {
    time_t t = ctime_max();
    printf("%s", ctime(&t));
    return 0;
}

对我来说,Tue Dec 31 23:59:59 2147483647 恰好是一年溢出四个有符号字节之前的第二个。

【讨论】:

    猜你喜欢
    • 2013-06-23
    • 1970-01-01
    • 1970-01-01
    • 2020-06-28
    • 1970-01-01
    • 1970-01-01
    • 2021-03-10
    • 1970-01-01
    • 2019-08-21
    相关资源
    最近更新 更多