【问题标题】:size of time_t and its max valuetime_t 的大小及其最大值
【发布时间】:2012-07-29 16:47:48
【问题描述】:
#include <stdio.h>
#include <time.h>

int main()
{
     printf("Size of time_t is %lu bytes.\n", sizeof(time_t));
     time_t biggest = 0x7fffffffffffffff;   // line 1
     printf("time_t's wrap around will be a second after %s.\n", asctime(gmtime(&biggest)) );

     return 0;
}

在 time.h 中,这是 time_t 的定义吗?

typedef  __darwin_time_t   time_t

如何解释它?由于我没有任何想法,所以我使用 sizeof 函数找到了 time_t = 8 个字节。

为什么第 1 行给出错误呢? 我收到此错误

Segmentation fault: 11

【问题讨论】:

  • 奇怪的是,标准似乎并没有强制要求包含time_t 最大值的常量。对于int 和大多数其他类型,它在limit.h 中进行了描述。 time_tsys/types.h 中有描述,但我找不到包含最大值的宏(time.h 中没有。
  • 如果删除第一个 printf() 是否仍然存在段错误?
  • 正如Greg所说,并不是所有的struct tm都可以保存time_t,当你使用gdb你可以看到gmtime(&biggest)返回的值总是NULL,这就解释了segFault。有关此 URL 的更多信息:lists.apple.com/archives/darwin-dev/2008/Apr/msg00098.html
  • 仅供参考,sizeof 是运算符而不是函数。

标签: c


【解决方案1】:

您对gmtime() 的调用可能会返回NULL(在我的Mac OS X 系统上会这样)。当您将此值传递给asctime() 时,您会得到一个异常(因为它需要一个非NULL 指针)。

并非所有time_t 值都可以在struct tm 中表示,这就是在这种情况下gmtime() 返回NULL 的原因。

【讨论】:

  • 请原谅,但我仍然不清楚。这是否意味着因为“struct tm”的成员是 int 类型,虽然 time_t 是 8 个字节,但它只能传递一个 int 类型在设置 MSB = 1 时可以容纳的最大值?
  • 基本上,是的。 struct tmtm_year 字段(至少在当前版本的 Mac OS X 上)不能保存与 time_t 的最大值关联的年份编号(当 time_t 是 64 位数量时)。跨度>
  • 格雷格成功了!这正是我的 64 位 Linux 机器上发生的事情。我有点震惊 struct tm 的成员在 x86_64 上是 int 的。
【解决方案2】:

虽然 time_t 的大小为 8,但在 64 位平台上,存在硬编码到运行时中的实现定义的限制,不能超过。当超出这些限制时,gmtime 将返回 NULL,并设置 errno 以指示错误的性质。您的代码无法检查 gmtime 返回的 NULL,因此 asctime 在尝试取消引用该空指针时会失败。这是您在使用惯用的 C 语言而不检查可能失败的函数的返回值时所面临的风险。

Windows 10 上的 Microsoft C gmtime 在传递 32535291600 时返回 NULL,并将 errno 设置为 EINVAL。尽管有人可能认为理论上的最大限制应该是 LLONG_MAX。 Microsoft 明确将限制设置为 _MAX__TIME64_T + _MAX_LOCAL_TIME。

来自 Microsoft Visual Studio 2010 CRT 中的 ctime.h 来源:

#define _MAX__TIME64_T 0x793406fffi64 /* number of seconds from 00:00:00, 01/01/1970 UTC to 23:59:59. 12/31/3000 UTC */ 

Apple 的 gmtime 函数在传递 67768036191676800 时返回 NULL 并将 errno 设置为 EOVERFLOW。Apple 实现在 asctime() 返回一年中超过 4 位的字符串的所有时间都表现出未定义的行为,因为 C 标准要求该函数返回不超过 26 个字符。

【讨论】:

    【解决方案3】:

    我查看了Linux头文件,发现了以下内容:

    /usr/include/time.h:
        typedef __time_t time_t;
    
    /usr/include/bits/types.h:
        __STD_TYPE __TIME_T_TYPE __time_t
    
    /usr/include/bits/typesizes.h
        #define __TIME_T_TYPE       __SLONGWORD_TYPE
    
    /usr/include/bits/types.h:
        #define __SLONGWORD_TYPE    long int
    

    所以time_t 的大小是long int。在 64 位机器上,您可能会得到 8 个字节。 然后我发现在我的 32 位 FreeBSD 上,它看起来像这样:

    /usr/include/machine/_types.h:
        typedef __int32_t   __time_t;   
    

    所以大小是 32 位。

    【讨论】:

      【解决方案4】:

      time_t 的底层类型可以是任何东西。这在很大程度上取决于您的系统。请参考类似问题:What primitive data type is time_t?

      线程中有一个链接指向sys/types.h 的描述,其中指出

      time_t 和clock_t 应为整数或实数浮点类型。

      另一个指向好答案的链接:https://stackoverflow.com/a/471287/276274

      【讨论】:

        猜你喜欢
        • 2011-08-02
        • 2017-09-26
        • 2016-02-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-10
        相关资源
        最近更新 更多