使用printf打印clock_t的正确方法是什么?
收藏

I'm currently using a explicit cast to unsigned long long and using %llu to print it, but since size_t has the %z specifier, why doesn't clock_t have one?

There isn't even a macro for it. Maybe I can assume that on an x64 system (OS and CPU) size_t is 8 bytes in length (and even in this case, they have provided %z), but what about clock_t?

最佳答案

There seems to be no perfect way. The root of the problem is that clock_t can be either integer or floating point.

clock_t可以是浮点类型

正如BastienLéonard在POSIX中提到的(赞成他),C99 N1256草案7.23.1 / 3也说:

[clock_t是]能够表示时间的算术类型

和6.2.5 / 18:

整数和浮点类型统称为算术类型。

该标准将算术类型定义为整数或浮点类型。

如果要除以CLOCKS_PER_SEC,请使用long double

The return value of clock() is implementation defined, and the only way to get standard meaning out of it is to divide by CLOCKS_PER_SEC to find the number of seconds:

clock_t t0 = clock();
/* Work. */
clock_t t1 = clock();
printf("%Lf", (long double)(t1 - t0));

由于以下两个原因,这虽然不够完美,但却足够好:

  • there seems to be no analogue to intmax_t for floating point types: How to get the largest precision floating point data type of implemenation and its printf specifier? So if a larger floating point type comes out tomorrow, it could be used and break your implementation.

  • if clock_t is an integer, the cast to float is well defined to use the nearest float possible. You may lose precision, but it would not matter much compared to the absolute value, and would only happen for huge amounts of time, e.g. long int in x86 is the 80-bit float with 64-bit significant, which is millions of years in seconds.

去投票说类似的柠檬水。

如果您认为它是整数,请使用%ju和uintmax_t

Although unsigned long long is currently the largest standard integer type possible:

因此,最好将类型转换为最大的无符号整数类型:

#include <stdint.h>

printf("%ju", (uintmax_t)(clock_t)1);

uintmax_t is guaranteed to have the size of the largest possible integer size on the machine.

uintmax_t and its printf specifier %ju were introduced in c99 and gcc for example implements them.

As a bonus, this solves once and for all the question of how to reliably printf integer types (which is unfortunately not the necessarily the case for clock_t).

如果是双重的话可能会出问题:

  • 如果太大而无法容纳整数,不确定的行为
  • 小于1的数字将四舍五入为0,您将看不到任何内容

由于这些后果比整数到浮点数转换要严重得多,因此使用浮点数可能是一个更好的主意。

在glibc 2.21上,它是一个整数

The manual says that using double is a better idea:

在GNU / Linux和GNU / Hurd系统上,clock_t等效于long int,而CLOCKS_PER_SEC是整数。但是在其他系统中,clock_t和宏CLOCKS_PER_SEC都可以是整数或浮点类型。如上例所示,将CPU时间值强制转换为两倍,可确保无论基础表示是什么,算术和打印之类的操作都能正常且一致地工作。

在glibc 2.21中:

也可以看看

  • 如何打印大小未知的类型(如ino_t)?
  • 如何使用printf显示off_t,nlink_t,size_t和其他特殊类型?

    公众号
    关注公众号订阅更多技术干货!