简体   繁体   English

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

[英]Format specifiers for implementation-defined types like time_t

I want to make my code more platform-/implementation-independent. 我想让我的代码更加平台/实现独立。 I don't know what a time_t will be implemented as on the platform when the code is being compiled. 在编译代码时,我不知道在平台上将实现什么time_t How do I know the type of t to determine what format specifier to use? 我如何知道t的类型以确定要使用的格式说明符?

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

Usually you can use a cast to convert the operand to some type for which you know the right format. 通常,您可以使用强制转换将操作数转换为您知道正确格式的某种类型。

Your proposed solution: 您提出的解决方案

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

clearly will not work, since time_t is a numeric type, not char* . 显然行不通的,因为time_t是数值型,不char*

We know, in general, that time_t is an arithmetic type. 通常,我们知道time_t是算术类型。 Something like this: 像这样的东西:

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

is likely to work on most systems. 可能适用于大多数系统。 It can fail (a) if time_t is an unsigned type no wider than unsigned long and the current value of t exceeds LONG_MAX , or (b) if time_t is a floating-point type. 它可能失败(a)如果time_t是无符号类型,不宽于unsigned long并且t的当前值超过LONG_MAX ,或者(b)如果time_t是浮点类型。

If you have C99 support, you can use long long , which is a little better: 如果你有C99支持,你可以使用long long ,这是一个更好的:

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

If you really want to go overboard with portability, you can detect what kind of type time_t is: 如果你真的想要过度使用可移植性,你可以检测出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);
}

You might want to tweak the %Lg format to something like %Lf or %.10Lf , depending on what output format you want. 您可能希望将%Lg格式调整为%Lg %Lf%.10Lf ,具体取决于您想要的输出格式。

Again, this assumes C99 support -- and you'll need #include <stdint.h> to make uintmax_t and intmax_t visible. 同样,这假设C99支持 - 您需要#include <stdint.h>才能使uintmax_tintmax_t可见。

time_t and clock_t are a bit unusual, in that the standard says only that they're arithmetic type capable of representing times. time_tclock_t有点不寻常,因为标准表示它们是能够表示时间的算术类型。 (In principle they could be complex types, but I'd say ignoring that possibility is worth the risk.) (原则上它们可能是复杂的类型,但我会说忽略这种可能性值得冒险。)

In most other cases, you'll probably know whether a given type is signed, unsigned, or floating-point, and you can just convert to the widest type of that kind. 在大多数其他情况下,您可能知道给定类型是有符号类型,无符号类型还是浮点数,并且您只能转换为最类型的类型。

Note that if you don't know how time_t is represented, you probably won't understand the output of the printf (such as 1379375215 ) either -- unless your goal is to figure that out. 请注意,如果您不知道time_t的表示方式,您可能无法理解printf的输出(例如1379375215 ) - 除非您的目标是弄明白。

(If you were programming in C++ rather than C, std::cout << t << "\\n"; would automatically use the correct overloaded operator<< .) (如果用C ++而不是C编程, std::cout << t << "\\n";会自动使用正确的重载operator<< 。)

If you want human-readable output (like Mon 2013-09-16 16:46:55 PDT ), you'll want to use one of the conversion functions declared in <time.h> , such as asctime() or strftime() . 如果你想要人类可读的输出(比如Mon 2013-09-16 16:46:55 PDT ),你会想要使用<time.h>声明的转换函数之一,例如asctime()strftime()

Generally, the way to display the value of a time_t is to break down its components to a struct tm using gmtime or localtime and display those or convert them as desired with strftime , or ctime to go directly from time_t to a string showing local time. 通常,显示time_t值的方法是使用gmtimelocaltime将其组件分解为struct tm并显示它们或根据需要使用strftimectime将它们直接从time_t转换为显示本地时间的字符串。

If you want to see the raw value for some purpose, the C standard specifies that time_t is real , which means it is integer or floating-point (C 2011 (N1570) 6.2.5 17). 如果您想出于某种目的看原始值,C标准指定time_t实数 ,这意味着它是整数或浮点数(C 2011(N1570)6.2.5 17)。 Therefore, you should be able to convert it to double and print that. 因此,您应该能够将其转换为double并打印出来。 There is some possibility that time_t can represent values that double cannot, so you might have to guard against that if you want to take care regarding exotic implementations. time_t可能代表double不能的值,因此如果你想要关注异国情调的实现,你可能不得不提防。 Since difftime returns the difference of two time_t objects as a double , it seems C does not truly support time_t with more precision than a double . 由于difftime将两个time_t对象的差异作为double ,因此C似乎并不真正支持time_t ,其精度高于double

You can use difftime() to obtain a double : 您可以使用difftime()来获取double

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

It is simple and I think it is portable. 它很简单,我认为它是便携式的。

The C standard says time_t will be a 'real type' (meaning an integer type or a floating point type, though in practice it is always an integer type). C标准说time_t将是'真实类型'(意思是整数类型或浮点类型,但实际上它总是整数类型)。

With time_t , your best bet is to format it with strftime() after analyzing it with localtime() or gmtime() — this can be done portably. 使用time_t ,最好的办法是在使用localtime()gmtime()分析后用strftime()格式化它 - 这可以通过移植来完成。

Unportably, you have to determine by some mechanism what is the correct format specifier. 不可思议的是,您必须通过某种机制确定什么是正确的格式说明符。 You might use PRI_[Xxodi]_time and SCN_[Xxodi]_time or something similar as a non-standard but close-to-standard (without trampling on the reserved namespace — which is names starting PRI or SCN followed by a lower-case letter or X). 您可以使用PRI_[Xxodi]_timeSCN_[Xxodi]_time或类似的非标准但接近标准的东西(不会践踏保留的命名空间 - 这是起始PRI或SCN后跟小写字母的名称或X)。 You use some mechanism to specify that...encapsulating the unportable information in one place. 您可以使用某种机制来指定...将不可移植的信息封装在一个地方。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM