什么是time_t最终是一个typedef?

时间:2009-01-22 23:12:55

标签: c linux types

我搜索了我的Linux盒子并看到了这个typedef:

typedef __time_t time_t;

但我找不到__time_t定义。

10 个答案:

答案 0 :(得分:158)

time_t Wikipedia article文章对此有所了解。底线是C规范中不保证time_t的类型。

  

time_t数据类型是一种数据类型   定义用于存储的ISO C库   系统时间值。这样的价值观是   从标准time()返回   库函数。这种类型是   typedef在标准中定义    头。 ISO C定义   time_t作为算术类型,但确实如此   不指定任何特定类型,   范围,分辨率或编码。   也没有具体说明的含义   适用于时间的算术运算   值。

     

符合Unix和POSIX标准的系统将time_t类型实现为signed integer(通常为32或64位宽)   表示秒数   自Unix纪元开始以来:   1970年1月1日午夜UTC(不是   计算闰秒)。一些系统   正确处理负时间值,   而其他人则没有。系统使用   32位time_t类型容易受到影响   Year 2038 problem

答案 1 :(得分:101)

[root]# cat time.c

#include <time.h>

int main(int argc, char** argv)
{
        time_t test;
        return 0;
}

[root]# gcc -E time.c | grep __time_t

typedef long int __time_t;

它在$INCDIR/bits/types.h到:

中定义
# 131 "/usr/include/bits/types.h" 3 4
# 1 "/usr/include/bits/typesizes.h" 1 3 4
# 132 "/usr/include/bits/types.h" 2 3 4

答案 2 :(得分:19)

<强>标准

William Brendel引用维基百科,但我更倾向于从马的嘴里说。

C99 N1256 standard draft 7.23.1 / 3“时间成分”说:

  

声明的类型是size_t(在7.17中描述)clock_t和time_t,它们是能够表示时间的算术类型

6.2.5 / 18“类型”说:

  

整数和浮点类型统称为算术类型。

POSIX 7 sys_types.h说:

  

[CX] time_t应为整数类型。

其中[CX]defined as

  

[CX]扩展到ISO C标准。

这是一个扩展,因为它提供了更强有力的保证:浮点数已经消失。

gcc one-liner

无需按照by Quassnoi所述创建文件:

echo | gcc -E -xc -include 'time.h' - | grep time_t

在Ubuntu 15.10 GCC 5.2上,前两行是:

typedef long int __time_t;
typedef __time_t time_t;

使用man gcc中的一些引号命令细分:

  • -E:“在预处理阶段后停止;不要正确运行编译器。”
  • -xc:指定C语言,因为输入来自没有文件扩展名的stdin。
  • -include file:“处理文件好像”#include“文件”“出现在主要源文件的第一行。”
  • -:来自stdin的输入

答案 3 :(得分:12)

答案肯定是特定于实施的。要明确找到您的平台/编译器,只需在代码中的某处添加此输出:

printf ("sizeof time_t is: %d\n", sizeof(time_t));

如果答案是4(32位)并且您的数据超出2038,那么您有25年的时间来迁移代码。

如果您将数据存储为字符串,那么您的数据就可以了,即使它很简单:

FILE *stream = [stream file pointer that you've opened correctly];
fprintf (stream, "%d\n", (int)time_t);

然后以同样的方式读回它(fread,fscanf等进入int),你就有了你的纪元偏移时间。 .Net中存在类似的解决方法。我在Win和Linux系统之间传递64位纪元数字没有问题(通过通信渠道)。这会带来字节排序问题,但这是另一个主题。

为了回答paxdiablo的问题,我会说它打印出“19100”,因为程序是用这种方式编写的(我承认我是在80年代自己做的):

time_t now;
struct tm local_date_time;
now = time(NULL);
// convert, then copy internal object to our object
memcpy (&local_date_time, localtime(&now), sizeof(local_date_time));
printf ("Year is: 19%02d\n", local_date_time.tm_year);

printf语句打印固定字符串“Year is:19”,后跟一个带有“自1900年以来的年份”的零填充字符串(tm->tm_year的定义)。在2000年,这个值显然是100。 "%02d"填充两个零,但如果长度超过两位则不截断。

正确的方法是(仅改为最后一行):

printf ("Year is: %d\n", local_date_time.tm_year + 1900);

新问题:这种想法的理由是什么?

答案 4 :(得分:7)

在Visual Studio 2008下,除非您定义__int64,否则默认为_USE_32BIT_TIME_T。你最好假装你不知道它被定义为什么,因为它可以(并且将会)从平台变为平台。

答案 5 :(得分:5)

time_t在64位计算机上的类型为 long int ,否则为 long long int

您可以在这些头文件中验证这一点:

time.h/usr/include
types.htypesizes.h/usr/include/x86_64-linux-gnu/bits

(以下陈述不是一个接一个。可以使用Ctrl + f搜索在resp。头文件中找到它们。)

1)在time.h

typedef __time_t time_t;

2)在types.h

# define __STD_TYPE     typedef  
__STD_TYPE __TIME_T_TYPE __time_t;  

3)在typesizes.h

#define __TIME_T_TYPE       __SYSCALL_SLONG_TYPE  
#if defined __x86_64__ && defined __ILP32__  
# define __SYSCALL_SLONG_TYPE   __SQUAD_TYPE  
#else
# define __SYSCALL_SLONG_TYPE   __SLONGWORD_TYPE
#endif  

4)再次在types.h

#define __SLONGWORD_TYPE    long int
#if __WORDSIZE == 32
# define __SQUAD_TYPE       __quad_t
#elif __WORDSIZE == 64
# define __SQUAD_TYPE       long int  

#if __WORDSIZE == 64
typedef long int __quad_t;  
#else
__extension__ typedef long long int __quad_t;

答案 6 :(得分:4)

在大多数传统平台上,它是32位有符号整数类型。但是,这会导致您的代码受year 2038 bug影响。因此,现代C库应该将其定义为带符号的64位int,这可以安全使用几十亿年。

答案 7 :(得分:3)

通常,您会在bitsasm标头目录中找到gcc的这些底层特定于实现的typedef。对我而言,它是/usr/include/x86_64-linux-gnu/bits/types.h

您可以通过grep或使用preprocessor invocation like that suggested by Quassnoi查看哪个特定标题。

答案 8 :(得分:1)

  

最终的time_t typedef是什么?

强大的代码并不关心类型是什么。

C种time_t真实类型,如double, long long, int64_t, int等。

它甚至可以是unsigned,因为许多时间函数的返回值指示错误不是-1,而是(time_t)(-1) - 这种实现选择并不常见。

重点是“需要知道”这种类型很少见。应编写代码以避免需要。

当代码想要打印原始time_t时,会发生常见的“需要知道”。转换为最宽的整数类型将适应大多数现代案例。

time_t now = 0;
time(&now);
printf("%jd", (intmax_t) now);
// or 
printf("%lld", (long long) now);

转换为doublelong double也可以,但可以提供不精确的十进制输出

printf("%.16e", (double) now);

答案 9 :(得分:-1)

对于8个字节(time_t),

typedef只是long long/__int64,所有编译器和操作系统都能理解。在以前的日子里,它曾经仅用于long int(4个字节)但现在不是。如果您查看time_t中的crtdefs.h,您会发现这两种实现,但操作系统将使用long long