我想让我的代码更加独立于平台/实现。我不知道time_t
编译代码时将在平台上实现什么。我如何知道类型t
来确定使用什么格式说明符?
...
time_t t = time(NULL);
printf("%s", t);
...
通常,您可以使用强制转换将操作数转换为您知道正确格式的某种类型。
您提出的解决方案:
time_t t = time(NULL);
printf("%s", t);
显然行不通,因为time_t
是数字类型,而不是char*
.
我们知道,一般来说,这time_t
是一种算术类型。像这样的东西:
printf("%ld\n", (long)t);
可能适用于大多数系统。它可能会失败(a)如果time_t
是无符号类型不大于unsigned long
并且当前值t
超过LONG_MAX
,或者(b)如果time_t
是浮点类型。
如果你有 C99 支持,你可以使用long long
,这样会好一点:
printf("%lld\n", (long long)t);
如果您真的想在可移植性方面做得过火,您可以检测出什么样的类型time_t
:
if ((time_t)-1 > 0) {
// time_t is an unsigned type
printf("%ju\n", (uintmax_t)t);
}
else if ((time_t)1 / 2 > 0) {
// time_t is a signed integer type
printf("%jd\n", (intmax_t)t);
}
else {
// time_t is a floating-point type (I've never seen this)
printf("%Lg\n", (long double)t);
}
您可能希望将%Lg
格式调整为%Lf
或%.10Lf
,具体取决于您想要的输出格式。
同样,这假设 C99 支持——你需要#include <stdint.h>
make uintmax_t
and intmax_t
visible 。
time_t
并且clock_t
有点不寻常,因为标准只说它们是能够表示时间的算术类型。(原则上它们可能是复杂的类型,但我想说忽略这种可能性是值得冒险的。)
在大多数其他情况下,您可能会知道给定类型是有符号、无符号还是浮点,并且您可以转换为该类型中最宽的类型。
请注意,如果您不知道如何time_t
表示,您可能也不会理解printf
(例如1379375215
)的输出——除非您的目标是弄清楚这一点。
(如果您使用 C++ 而不是 C 进行编程,std::cout << t << "\n";
将自动使用正确的重载operator<<
.)
如果您想要人类可读的输出(如Mon 2013-09-16 16:46:55 PDT
),则需要使用 中声明的转换函数之一<time.h>
,如asctime()
或strftime()
。
通常,显示 a 值的方法time_t
是将其组件分解为struct tm
使用gmtime
orlocaltime
并显示这些组件或使用 转换它们strftime
,或者ctime
直接从time_t
显示本地时间的字符串转到。
如果您想出于某种目的查看原始值,C 标准指定它time_t
是real,这意味着它是整数或浮点数 (C 2011 (N1570) 6.2.5 17)。因此,您应该能够将其转换为double
并打印出来。有一些可能性time_t
可以表示不能表示的值double
,因此如果您想注意异国情调的实现,您可能不得不提防这种情况。由于difftime
将两个time_t
对象的差异返回为 a double
,因此似乎 C 并不真正支持time_t
比 a 更精确的精度double
。
您可以使用difftime()
获取double
:
time_t t = time(NULL);
printf("seconds 1970->now: %.f\n", difftime(t, (time_t) 0));
它很简单,我认为它是便携式的。
C 标准说time_t
将是“真实类型”(表示整数类型或浮点类型,尽管实际上它始终是整数类型)。
使用time_t
,您最好的选择是在使用or对其strftime()
进行分析后对其进行格式化——这可以便携地完成。localtime()
gmtime()
不可移植的是,您必须通过某种机制确定什么是正确的格式说明符。您可以使用PRI_[Xxodi]_time
andSCN_[Xxodi]_time
或类似的东西作为非标准但接近标准的东西(不践踏保留的命名空间——即以 PRI 或 SCN 开头的名称,后跟小写字母或 X)。您使用某种机制来指定……将不可移植的信息封装在一个地方。