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

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

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

通常,显示time_t值的方法是使用gmtimelocaltime将其组件分解为struct tm并显示它们或根据需要使用strftimectime将它们直接从time_t转换为显示本地时间的字符串。

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

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

您提出的解决方案

 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格式调整为%Lg %Lf%.10Lf ,具体取决于您想要的输出格式。

同样,这假设C99支持 – 您需要#include 才能使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 ),你会想要使用声明的转换函数之一,例如asctime()strftime()

您可以使用difftime()来获取double

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

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

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

使用time_t ,最好的办法是在使用localtime()gmtime()进行分析后用strftime()格式化它 – 这可以通过移植来完成。

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