我目前正在使用unsigned long long
显式转换并使用%llu
进行打印,但由于size_t
具有%z
说明符,为什么不clock_t
1}}有一个?
甚至没有宏观。也许我可以假设在x64系统上(操作系统和CPU)size_t
的长度为8个字节(即使在这种情况下,它们也提供了%z
),但是clock_t
呢?
答案 0 :(得分:25)
似乎没有完美的方式。问题的根源是clock_t
可以是整数或浮点。
clock_t可以是浮点类型
作为POSIX的Bastien Léonard mentions(向上投票),C99 N1256 draft 7.23.1 / 3也说:
[clock_t]是能够表示时间的算术类型
和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
:How to get the largest precision floating point data type of implemenation and its printf specifier?因此,如果明天出现更大的浮点类型,则可以使用它并破坏您的实现。
如果clock_t
是一个整数,则将float定义为使用最近的float。你可能会失去精确度,但与绝对值相比它并不重要,并且只会在很长一段时间内发生,例如: x86中的long int
是具有64位有效值的80位浮点数,这是几百万年的秒数。
Go upvote lemonad谁说了类似的东西。
如果您认为它是一个整数,请使用%ju和uintmax_t
虽然unsigned long long
是目前可能的最大标准整数类型:
clock_t
可能是其中之一因此最好将类型转换为可能的最大无符号整数类型:
#include <stdint.h>
printf("%ju", (uintmax_t)(clock_t)1);
保证 uintmax_t
具有机器上可能的最大整数大小。
uintmax_t
及其printf说明符%ju
在c99中引入,例如gcc实现它们。
作为奖励,这一劳永逸地解决了如何可靠printf
整数类型的问题(遗憾的是clock_t
不一定是这种情况)。
如果它是双重的话会出现什么问题:
由于这些后果比整数到浮点转换要严厉得多,因此使用float可能是一个更好的主意。
在glibc 2.21上,它是一个整数
手册说使用double
是一个更好的主意:
在GNU / Linux和GNU / Hurd系统上,clock_t等效于long int,CLOCKS_PER_SEC是整数值。但在其他系统中,clock_t和宏CLOCKS_PER_SEC都可以是整数或浮点类型。将CPU时间值转换为加倍,如上例所示,确保算术和打印等操作无论底层表示是什么都能正常且一致地工作。
在glibc 2.21中:
clock_t
是long int
:
__clock_t
__CLOCK_T_TYPE
__SLONGWORD_TYPE
long int
clock()
是使用sys_clock_gettime
实现的:
__clock_gettime
SYSDEP_GETTIME_CPU
SYSCALL_GETTIME
,最终进行内联系统调用 man clock_gettime
告诉我们,它会返回struct timespec
,其中GCC中包含long int
个字段。
因此底层实现确实会返回整数。
另见
答案 1 :(得分:11)
这可能是因为时钟滴答不是一个非常明确的单位。您可以将其转换为秒并将其打印为double:
time_in_seconds = (double)time_in_clock_ticks / (double)CLOCKS_PER_SEC;
printf("%g seconds", seconds);
CLOCKS_PER_SEC宏扩展为表示一秒钟内时钟滴答数的表达式。
答案 2 :(得分:11)
据我所知,你所做的事情是最好的。除了clock_t
可能是真实的类型:
time_t
和clock_t
应为整数或实数浮点类型。
http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/types.h.html
答案 3 :(得分:3)
C标准必须适应各种各样的架构,除了内部时钟类型是算术的事实之外,它不可能做出任何进一步的保证。
在大多数情况下,您对时间间隔感兴趣,因此我将时钟滴答的差异转换为毫秒。 unsigned long
大到足以代表近50天的间隔,即使它是32位,所以对于大多数情况它应该足够大:
clock_t start;
clock_t end;
unsigned long millis = (end - start) * 1000 / CLOCKS_PER_SEC;
答案 4 :(得分: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;
}