我目前在使用显式转换为unsigned long long
,并使用%llu
打印它,但由于size_t
有%z
说明符,为什么clock_t
没有呢?
甚至没有一个宏来支持。也许我可以假设在x64系统上(操作系统和CPU),size_t
的长度为8字节(即使在这种情况下,他们也提供了%z
),但是clock_t
呢?
似乎没有完美的方法。问题的根源在于clock_t
既可以是整数也可以是浮点数。
clock_t
可以是浮点类型
正如Bastien Léonard提到POSIX(请为他投票),C99 N1256 draft7.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
的浮点类型:如何获取实现中最大精度的浮点数据类型及其printf说明符? 因此,如果明天出现更大的浮点类型,则可以使用并破坏您的实现。
如果clock_t
是整数,则将其转换为浮点数定义良好,以使用最接近的可能浮点数。您可能会失去精度,但与绝对值相比,这并不重要,并且只会在大量时间(例如,在x86中的long int
是具有64位有效数字的80位浮点数,相当于数百万年)内发生。
赞同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
来说,这不一定是必需的)。
如果是double,会出现什么问题:
由于这些后果比整数转换成浮点数更为严重,因此使用float可能是一个更好的选择。
在glibc 2.21上,它是整数
手册说使用double
是一个更好的选择:
clock_t
是 long int
类型:
__clock_t
__CLOCK_T_TYPE
__SLONGWORD_TYPE
long int
Linux 中的 clock()
是使用 sys_clock_gettime
实现的:
__clock_gettime
SYSDEP_GETTIME_CPU
SYSCALL_GETTIME
,最终进行一个内联系统调用man clock_gettime
告诉我们它返回一个 struct timespec
结构体,在 GCC 中包含 long int
字段。
所以底层实现的确会返回整数。
另请参阅
clock_t
可能是一个实际类型:
请参阅:http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/types.h.html
time_t
和clock_t
应该是整数或实浮点数类型。
uintmax_t
和%ju
来获取整数一样?那将是最优的方式。 - Ciro Santilli OurBigBook.com可能是因为时钟滴答不是一个非常明确定义的单位。您可以将其转换为秒并打印为double:
time_in_seconds = (double)time_in_clock_ticks / (double)CLOCKS_PER_SEC;
printf("%g seconds", seconds);
CLOCKS_PER_SEC宏会展开为一个表达式,表示每秒钟时钟计时器的数目。
long double
,因为它可能具有更高的精度2)在除法之后执行单个类型转换:(long double)(time_in_clock_ticks / CLOCKS_PER_SEC)
,以便只舍入一次。 - Ciro Santilli OurBigBook.comC标准必须适应各种架构,这使得除了内部时钟类型是算术的这一事实外,不可能作出任何进一步的保证。
在大多数情况下,您关心的是时间间隔,因此我会将时钟滴答数的差异转换为毫秒。即使它是32位的,无符号长整型足以表示近50天的时间间隔,因此对于大多数情况来说,它应该足够大:
clock_t start;
clock_t end;
unsigned long millis = (end - start) * 1000 / CLOCKS_PER_SEC;
clock_t
是整数还是浮点值;如果您想要做任何有用的事情,您必须将其与CLOCKS_PER_SEC
相关联,而这超出了printf()
的领域。 - Christoph 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;
}
%ju
?这会打印出ju
。 - Victorgcc -std=c99
编译的吗(或者告诉你的编译器使用c99)?你的编译器版本是什么?我刚测试了一下,在我的gcc --version
等于gcc (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3
下,以下代码可以正常工作:printf( "printf uintmax_t = %ju\n", (uintmax_t)1 );
。 - Ciro Santilli OurBigBook.com