我搜索了我的Linux盒子并看到了这个typedef:
typedef __time_t time_t;
但我找不到__time_t
定义。
答案 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“类型”说:
整数和浮点类型统称为算术类型。
[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.h
和typesizes.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)
通常,您会在bits
或asm
标头目录中找到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);
转换为double
或long double
也可以,但可以提供不精确的十进制输出
printf("%.16e", (double) now);
答案 9 :(得分:-1)
time_t
), typedef
只是long long/__int64
,所有编译器和操作系统都能理解。在以前的日子里,它曾经仅用于long int
(4个字节)但现在不是。如果您查看time_t
中的crtdefs.h
,您会发现这两种实现,但操作系统将使用long long
。