【问题标题】:Format specifiers for implementation-defined types like time_t实现定义类型的格式说明符,例如 time_t
【发布时间】:2013-09-21 06:05:27
【问题描述】:

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

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

【问题讨论】:

  • 以您的非便携方式,是否可以保证有效内存中有一个空终止符?
  • 这不是真正的问题。你知道我问的问题的答案吗?
  • 否,但没有任何便携式解决方案,您的非便携式解决方案仍不应调用 UB。
  • 这只是一个例子,让我对类型打印的问题更清楚。

标签: c printf typedef time-t


【解决方案1】:

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

您提出的解决方案:

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> 才能使 uintmax_tintmax_t 可见。

time_tclock_t 有点不寻常,因为标准规定它们是能够表示时间的算术类型。 (原则上它们可能是复杂类型,但我会说忽略这种可能性是值得冒险的。)

在大多数其他情况下,您可能会知道给定类型是有符号、无符号还是浮点,并且您可以转换为该类型中最宽的类型。

请注意,如果您不知道time_t 是如何表示的,那么您可能也不会理解printf(例如1379375215)的输出——除非您的目标是弄清楚这一点。

(如果您使用 C++ 而不是 C 进行编程,std::cout << t << "\n"; 将自动使用正确的重载 operator<<。)

如果您想要人类可读的输出(例如Mon 2013-09-16 16:46:55 PDT),您需要使用<time.h> 中声明的转换函数之一,例如asctime()strftime() .

【讨论】:

  • 这一行是什么意思 --> "if ((time_t)-1 > 0) {" ? (谢谢)
  • @Moytaba:当且仅当time_t 是无符号整数类型时,该条件才成立。将负值 (-1) 转换为无符号类型会产生正结果。
【解决方案2】:

通常,显示time_t 值的方法是使用gmtimelocaltime 将其组件分解为struct tm,然后使用strftime 或@ 显示或转换它们。 987654326@ 直接从time_t 转到显示当地时间的字符串。

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

【讨论】:

    【解决方案3】:

    您可以使用difftime() 获取double

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

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

    【讨论】:

    • 这是迄今为止最好的解决方案。它也非常简单和可移植(Linux、FreeBSD)。
    【解决方案4】:

    C 标准规定 time_t 将是“实类型”(表示整数类型或浮点类型,但实际上它始终是整数类型)。

    对于time_t,最好的办法是在使用localtime()gmtime() 对其进行分析后使用strftime() 对其进行格式化——这可以通过便携方式完成。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-06
      • 1970-01-01
      • 1970-01-01
      • 2020-05-23
      • 1970-01-01
      • 2023-03-10
      • 2020-10-07
      • 1970-01-01
      相关资源
      最近更新 更多