30

我想让我的代码更加独立于平台/实现。我不知道time_t编译代码时将在平台上实现什么。我如何知道类型t来确定使用什么格式说明符?

...
time_t t = time(NULL);
printf("%s", t);
...
4

4 回答 4

27

通常,您可以使用强制转换将操作数转换为您知道正确格式的某种类型。

您提出的解决方案:

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_tand intmax_tvisible 。

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()

于 2013-09-16T23:46:07.433 回答
11

通常,显示 a 值的方法time_t是将其组件分解为struct tm使用gmtimeorlocaltime并显示这些组件或使用 转换它们strftime,或者ctime直接从time_t显示本地时间的字符串转到。

如果您想出于某种目的查看原始值,C 标准指定它time_treal,这意味着它是整数或浮点数 (C 2011 (N1570) 6.2.5 17)。因此,您应该能够将其转换为double并打印出来。有一些可能性time_t可以表示不能表示的值double,因此如果您想注意异国情调的实现,您可能不得不提防这种情况。由于difftime将两个time_t对象的差异返回为 a double,因此似乎 C 并不真正支持time_t比 a 更精确的精度double

于 2013-09-16T23:42:30.323 回答
8

您可以使用difftime()获取double

time_t t = time(NULL);
printf("seconds 1970->now: %.f\n", difftime(t, (time_t) 0));

它很简单,我认为它是便携式的。

于 2015-12-05T17:04:45.540 回答
3

C 标准说time_t将是“真实类型”(表示整数类型或浮点类型,尽管实际上它始终是整数类型)。

使用time_t,您最好的选择是在使用or对其strftime()进行分析后对其进行格式化——这可以便携地完成。localtime()gmtime()

不可移植的是,您必须通过某种机制确定什么是正确的格式说明符。您可以使用PRI_[Xxodi]_timeandSCN_[Xxodi]_time或类似的东西作为非标准但接近标准的东西(不践踏保留的命名空间——即以 PRI 或 SCN 开头的名称,后跟小写字母或 X)。您使用某种机制来指定……将不可移植的信息封装在一个地方。

于 2013-09-16T23:47:37.467 回答