实现定义类型的格式说明符,如time_t

时间:2013-09-16 23:32:29

标签: c printf typedef time-t

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

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

4 个答案:

答案 0 :(得分:23)

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

您提出的解决方案:

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

显然有效,因为time_t是数字类型,而不是char*

我们知道,time_t一般是算术类型。像这样:

 printf("%ld\n", (long)t);

可能适用于大多数系统。它可能失败(a)如果time_t是无符号类型且不超过unsigned longt的当前值超过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>中声明的转换函数之一,例如{{1 }或asctime()

答案 1 :(得分:10)

通常,显示time_t值的方法是使用struct tmgmtime将其组件细分为localtime并显示或转换为strftime需要使用ctimetime_t直接从time_t转到显示当地时间的字符串。

如果您想出于某种目的查看原始值,C标准指定double real ,这意味着它是整数或浮点数(C 2011(N1570)) 6.2.5 17)。因此,您应该能够将其转换为time_t并打印出来。 double可能代表difftime无法表达的值,因此如果您想要关注异国情调的实施,则可能需要提防。由于time_t将两个double个对象的差异作为time_t返回,因此C似乎并不真正支持double的精度高于{{1}}。

答案 2 :(得分:5)

您可以使用difftime()获取double

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

这很简单,我觉得它很便携。

答案 3 :(得分:3)

C标准说time_t将是'真实类型'(意思是整数类型或浮点类型,但实际上它总是整数类型)。

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

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