ctime 返回 null

发布于 2024-11-07 15:55:17 字数 384 浏览 6 评论 0原文

如果用户类型 time_t 定义为 __darwin_time_t,它本身在 MacOS X 中定义为 long,为什么下面的代码会输出 8 时间是(空)?也许这很愚蠢,但我真的无法理解。

#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;
}

If the user type time_t is defined as __darwin_time_t, which itself is defined as long in MacOS X, why does the following code outputs 8 Time is (null)? Maybe it's something silly, but I can't really understand it.

#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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

冷情 2024-11-14 15:55:17

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

Time 0x7FFFFFFFFFFFFFFF appears to be around the year 292,471,210,647 AD, which undoubtedly causes ctime to exceed the 26 characters it is guaranteed by C99, so it returns NULL rather than overflowing its buffer. In general, try to avoid any dates that occur after the Morlocks go to war with the Eloi.

多孤肩上扛 2024-11-14 15:55:17

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

While working through the book "Expert C Programming", I ran across the same problem in Lion 10.7.3 -- with t=0xf0c00000000000, ctime(&t) yields Wed Mar 1 21:07:12 214739252 and with t=0xf0d00000000000, ctime(&t) returns the null pointer (0x0).
So it doesn't appear to be a wrap around for t, but some test inside ctime(&t) that returns the null pointer if t is too large.

薯片软お妹 2024-11-14 15:55:17

来自 glibc 的实现我们读到:

我们限制了可以打印的年份的大小。使用%d
使用格式说明符添加 1900 会溢出
数字和负值被打印。对于某些架构我们
理论上可以使用 %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,这恰好是该年溢出四个有符号字节之前的第二个。

From glibc's implementation we read:

We limit the size of the year which can be printed. Using the %d
format specifier used the addition of 1900 would overflow the
number and a negative vaue is printed. For some architectures we
could in theory use %ld or an evern larger integer format but
this would mean the output needs more space. This would not be a
problem if the 'asctime_r' interface would be defined sanely and
a buffer size would be passed.

Run the program below to find the exact limit on your machine.

#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;
}

For me that comes out to Tue Dec 31 23:59:59 2147483647 which happens to be the second before the year overflows four signed bytes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文