2011-05-17 149 views
0

如果用户类型time_t被定义为__darwin_time_t,它本身在MacOS X中定义为long,为什么下面的代码输出8 Time is (null)?也许这是愚蠢的,但我不能真正理解它。ctime返回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; 
} 
+0

我的意思是'__darwin_time_t',而不是'__darwin_time',对不起。 – sidyll 2011-05-17 18:01:41

回答

7

时间0x7FFFFFFFFFFFFFFF似乎是围绕今年292471210647 AD,这无疑会导致ctime超过26个字符它是由C99保证,所以它返回NULL,而不是它的溢出缓冲区。一般来说,尽量避免在Morlock与Eloi交战之后发生的任何日期。

+1

嗯,这个想法是要找出'time_t'什么时候会环绕。 Unix时代的0x7FFFFFFF将在2038年发生,所以我想我们需要一个新的标准,然后星系间的战争开始发生在银河系中。 – sidyll 2011-05-17 18:21:47

+1

改为尝试strftime。或者只是检查localtime或gmtime的tm_year。 – Random832 2011-05-17 19:11:43

2

虽然经书“C专家编程”的工作,我碰到了同样的问题在狮跑10.7.3 - 与t=0xf0c00000000000ctime(&t)产量Wed Mar 1 21:07:12 214739252t=0xf0d00000000000, ctime(&t)返回空指针(为0x0)。 所以它看起来并不是对t的包装,但是在ctime(&t)里面的一些测试在t太大时返回空指针。

+2

只是做了同样的事情。滑稽。 – Suboptimus 2013-07-19 21:01:16

1

glibc's implementation,我们读到:

我们限制可打印的大小年。使用%d 格式说明符时,使用1900的补充将溢出 号码并打印负值。对于某些体系结构,我们 理论上可以使用%ld或evern较大的整数格式,但这可能意味着输出需要更多空间。如果'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这恰好是第二年溢出4个符号字节之前。