34

我目前正在使用显式强制转换unsigned long long并使用%llu来打印它,但是既然size_t有说明%z符,为什么没有clock_t呢?

甚至没有宏。也许我可以假设在 x64 系统(操作系统和 CPU)size_t上的长度为 8 个字节(即使在这种情况下,他们也提供了%z),但是呢clock_t

4

5 回答 5

31

似乎没有完美的方法。问题的根源在于它clock_t可以是整数或浮点数。

clock_t 可以是浮点类型

正如Bastien Léonard为 POSIX 提到的(给他投票),C99 N1256 草案7.23.1/3 也说:

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

和 6.2.5/18:

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

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

如果您将除以 CLOCKS_PER_SEC,请使用 long double

的返回值clock()是实现定义的,从中获得标准含义的唯一方法是除以CLOCKS_PER_SEC找到秒数:

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

这已经足够了,尽管并不完美,原因有以下两个:

  • intmax_t浮点类型似乎没有类似物:如何获得实现的最大精度浮点数据类型及其 printf 说明符?因此,如果明天出现更大的浮点类型,它可能会被使用并破坏您的实现。

  • 如果clock_t是整数,则强制转换为浮点数被明确定义为使用最接近的浮点数。您可能会失去精度,但与绝对值相比,这无关紧要,并且只会在很长一段时间内发生,例如long int在 x86 中是具有 64 位有效位的 80 位浮点数,即数百万年以秒为单位。

去投票给说类似话的柠檬水。

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

虽然unsigned long long是目前可能的最大标准整数类型:

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

#include <stdint.h>

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

uintmax_t保证具有机器上可能的最大整数大小的大小。

uintmax_t它的 printf 说明符%ju是在 c99 中引入的,例如 gcc 实现了它们。

作为奖励,这一劳永逸地解决了如何可靠地printf整数类型的问题(不幸的是,这不一定是这种情况clock_t)。

如果它是双重的,可能会出现什么问题:

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

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

在 glibc 2.21 上它是一个整数

该手册说使用double是一个更好的主意:

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

在 glibc 2.21 中:

也可以看看

于 2013-06-19T12:02:20.307 回答
12

据我所知,你的做法是最好的。除了这clock_t可能是一个真实的类型:

time_t并且clock_t应该是整数或实浮点类型。

http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/types.h.html

于 2009-07-04T23:14:23.987 回答
11

这可能是因为时钟滴答不是一个非常明确的单位。您可以将其转换为秒并将其打印为双精度:

time_in_seconds = (double)time_in_clock_ticks / (double)CLOCKS_PER_SEC;
printf("%g seconds", seconds);

CLOCKS_PER_SEC 宏扩展为表示一秒内时钟滴答数的表达式。

于 2009-07-04T23:12:30.763 回答
4

C 标准必须适应各种各样的体系结构,这使得除了内部时钟类型是算术这一事实之外无法做出任何进一步的保证。

在大多数情况下,您对时间间隔感兴趣,因此我会将时钟滴答的差异转换为毫秒。Anunsigned long足够大,即使它是 32 位,也足以表示近 50 天的间隔,因此对于大多数情况它应该足够大:

clock_t start;
clock_t end;
unsigned long millis = (end - start) * 1000 / CLOCKS_PER_SEC;
于 2009-07-05T00:19:13.017 回答
1

一种方法是使用gettimeofday函数。可以使用此功能找到差异:

unsigned long  diff(struct timeval second, struct timeval first)
{
    struct timeval  lapsed;
    struct timezone tzp;
    unsigned long t;

    if (first.tv_usec > second.tv_usec) {
        second.tv_usec += 1000000;
        second.tv_sec--;
    }

    lapsed.tv_usec = second.tv_usec - first.tv_usec;
    lapsed.tv_sec  = second.tv_sec  - first.tv_sec;
    t = lapsed.tv_sec*1000000 + lapsed.tv_usec;

    printf("%lu,%lu - %lu,%lu = %ld,%ld\n",
           second.tv_sec, second.tv_usec,
           first.tv_sec,  first.tv_usec,
           lapsed.tv_sec, lapsed.tv_usec);

    return t;
}
于 2009-12-22T11:23:01.663 回答