time_t 最终是什么类型的定义?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/471248/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is time_t ultimately a typedef to?
提问by kal
I searched my Linux box and saw this typedef:
我搜索了我的 Linux 盒子,看到了这个 typedef:
typedef __time_t time_t;
But I could not find the __time_t
definition.
但我找不到__time_t
定义。
采纳答案by William Brendel
The time_t Wikipedia articlearticle sheds some light on this. The bottom line is that the type of time_t
is not guaranteed in the C specification.
该time_t的维基百科文章文章揭示了一些这方面的光。最重要的是,time_t
C 规范中不保证的类型。
The
time_t
datatype is a data type in the ISO C library defined for storing system time values. Such values are returned from the standardtime()
library function. This type is a typedef defined in the standard header. ISO C defines time_t as an arithmetic type, but does not specify any particular type, range, resolution, or encoding for it. Also unspecified are the meanings of arithmetic operations applied to time values.Unix and POSIX-compliant systems implement the
time_t
type as asigned integer
(typically 32 or 64 bits wide) which represents the number of seconds since the start of the Unix epoch: midnight UTC of January 1, 1970 (not counting leap seconds). Some systems correctly handle negative time values, while others do not. Systems using a 32-bittime_t
type are susceptible to the Year 2038 problem.
的
time_t
数据类型是用于存储系统时间值所定义的ISO C库中的数据类型。这些值是从标准time()
库函数返回的。此类型是标准头文件中定义的 typedef。ISO C 将 time_t 定义为算术类型,但没有为其指定任何特定类型、范围、分辨率或编码。同样未指定的是应用于时间值的算术运算的含义。Unix 和 POSIX 兼容系统将
time_t
类型实现为 asigned integer
(通常为 32 或 64 位宽),它表示自 Unix 纪元开始以来的秒数:UTC 午夜 1970 年 1 月 1 日(不计算闰秒)。一些系统正确处理负时间值,而其他系统则不能。使用 32 位time_t
类型的系统容易受到2038 年问题的影响。
回答by Eclipse
Under Visual Studio 2008, it defaults to an __int64
unless you define _USE_32BIT_TIME_T
. You're better off just pretending that you don't know what it's defined as, since it can (and will) change from platform to platform.
在 Visual Studio 2008 下,__int64
除非您定义_USE_32BIT_TIME_T
. 你最好假装你不知道它的定义是什么,因为它可以(并且将会)从平台到平台改变。
回答by Quassnoi
[root]# cat time.c
[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
[root]# gcc -E time.c | grep __time_t
typedef long int __time_t;
typedef long int __time_t;
It's defined in $INCDIR/bits/types.h
through:
它$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
回答by Quassnoi
It's a 32-bit signed integer type on most legacy platforms. However, that causes your code to suffer from the year 2038 bug. So modern C libraries should be defining it to be a signed 64-bit int instead, which is safe for a few billion years.
它是大多数遗留平台上的 32 位有符号整数类型。但是,这会导致您的代码遭受2038 年错误。所以现代 C 库应该将它定义为一个有符号的 64 位 int,这在几十亿年内都是安全的。
回答by bvrwoo_3376
time_t
is just typedef
for 8 bytes (long long/__int64
) which all compilers and OS's understand. Back in the days, it used to be just for long int
(4 bytes) but not now. If you look at the time_t
in crtdefs.h
you will find both implementations but the OS will use long long
.
time_t
仅typedef
适用于long long/__int64
所有编译器和操作系统都能理解的8 个字节 ( )。过去,它曾经只是long int
(4 个字节),但现在不是。如果您查看time_t
in,crtdefs.h
您会发现两种实现方式,但操作系统将使用long long
.
回答by poolie
Typically you will find these underlying implementation-specific typedefs for gcc in the bits
or asm
header directory. For me, it's /usr/include/x86_64-linux-gnu/bits/types.h
.
通常,您会在bits
或asm
标头目录中找到这些针对 gcc 的底层实现特定的 typedef 。对我来说,是/usr/include/x86_64-linux-gnu/bits/types.h
。
You can just grep, or use a preprocessor invocation like that suggested by Quassnoito see which specific header.
您可以只使用 grep 或使用Quassnoi 建议的预处理器调用来查看哪个特定标头。
回答by pwrgreg007
The answer is definitely implementation-specific. To find out definitively for your platform/compiler, just add this output somewhere in your code:
答案肯定是特定于实现的。要确定您的平台/编译器,只需在代码中的某处添加此输出:
printf ("sizeof time_t is: %d\n", sizeof(time_t));
If the answer is 4 (32 bits) and your data is meant to go beyond 2038, then you have 25 years to migrate your code.
如果答案是 4(32 位)并且您的数据要超过2038 年,那么您有 25 年的时间来迁移您的代码。
Your data will be fine if you store your data as a string, even if it's something simple like:
如果您将数据存储为字符串,您的数据会很好,即使它很简单,例如:
FILE *stream = [stream file pointer that you've opened correctly];
fprintf (stream, "%d\n", (int)time_t);
Then just read it back the same way (fread, fscanf, etc. into an int), and you have your epoch offset time. A similar workaround exists in .Net. I pass 64-bit epoch numbers between Win and Linux systems with no problem (over a communications channel). That brings up byte-ordering issues, but that's another subject.
然后只需以相同的方式将其读回(fread、fscanf 等,将其读入 int),然后您就有了 epoch 偏移时间。.Net 中存在类似的解决方法。我在 Win 和 Linux 系统之间传递 64 位纪元数没有问题(通过通信通道)。这带来了字节顺序问题,但这是另一个主题。
To answer paxdiablo's query, I'd say that it printed "19100" because the program was written this way (and I admit I did this myself in the '80's):
要回答 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);
The printf
statement prints the fixed string "Year is: 19" followed by a zero-padded string with the "years since 1900" (definition of tm->tm_year
). In 2000, that value is 100, obviously. "%02d"
pads with two zeros but does not truncate if longer than two digits.
该printf
语句打印固定字符串“Year is: 19”,后跟带有“years since 1900”(定义为tm->tm_year
)的零填充字符串。在 2000 年,该值显然是 100。"%02d"
用两个零填充,但如果长度超过两位数,则不会截断。
The correct way is (change to last line only):
正确的方法是(仅更改为最后一行):
printf ("Year is: %d\n", local_date_time.tm_year + 1900);
New question: What's the rationale for that thinking?
新问题:这种想法的基本原理是什么?
回答by abcoep
time_t
is of type long int
on 64 bit machines, else it is long long int
.
time_t
是long int
64 位机器上的类型,否则是long long int
.
You could verify this in these header files:
您可以在这些头文件中验证这一点:
time.h
: /usr/include
types.h
and typesizes.h
: /usr/include/x86_64-linux-gnu/bits
time.h
:/usr/include
types.h
和typesizes.h
:/usr/include/x86_64-linux-gnu/bits
(The statements below are not one after another. They could be found in the resp. header file using Ctrl+f search.)
(下面的语句不是一个接一个。它们可以在相应的头文件中使用 Ctrl+f 搜索找到。)
1)In time.h
1)输入 time.h
typedef __time_t time_t;
2)In types.h
2)输入 types.h
# define __STD_TYPE typedef
__STD_TYPE __TIME_T_TYPE __time_t;
3)In typesizes.h
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) Again in types.h
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;
回答by chux - Reinstate Monica
What is ultimately a time_t typedef to?
time_t typedef 最终是什么?
Robust code does not care what the type is.
健壮的代码不关心类型是什么。
C species time_t
to be a real typelike double, long long, int64_t, int
, etc.
C 种time_t
是真正的类型,如double, long long, int64_t, int
等。
It even could be unsigned
as the return values from many time function indicating error is not -1
, but (time_t)(-1)
- This implementation choice is uncommon.
它甚至可以unsigned
作为指示错误的多次函数的返回值不是-1
,但是(time_t)(-1)
- 这种实现选择并不常见。
The point is that the "need-to-know" the type is rare. Code should be written to avoid the need.
关键是“需要知道”的类型很少见。应该编写代码以避免这种需要。
Yet a common "need-to-know" occurs when code wants to print the raw time_t
. Casting to the widest integer type will accommodate most modern cases.
然而,当代码想要打印原始time_t
. 转换为最宽的整数类型将适应大多数现代情况。
time_t now = 0;
time(&now);
printf("%jd", (intmax_t) now);
// or
printf("%lld", (long long) now);
Casting to a double
or long double
will work too, yet could provide inexactdecimal output
转换为double
orlong double
也可以工作,但可能提供不精确的十进制输出
printf("%.16e", (double) now);