C 什么&x2019;使用printf打印时钟的正确方法是什么?
我目前正在使用显式转换到C 什么&x2019;使用printf打印时钟的正确方法是什么?,c,io,printf,clock,C,Io,Printf,Clock,我目前正在使用显式转换到unsigned long long并使用%llu打印它,但是既然size\u t有%z说明符,为什么clock\u t没有呢 甚至连宏都没有。也许我可以假设在x64系统(操作系统和CPU)上,size\u t的长度为8字节(即使在这种情况下,他们也提供了%z),但是clock\u t呢?这可能是因为时钟信号不是一个很好定义的单位。您可以将其转换为秒,并以双精度打印: time_in_seconds = (double)time_in_clock_ticks / (dou
unsigned long long
并使用%llu
打印它,但是既然size\u t
有%z
说明符,为什么clock\u t
没有呢
甚至连宏都没有。也许我可以假设在x64系统(操作系统和CPU)上,
size\u t
的长度为8字节(即使在这种情况下,他们也提供了%z
),但是clock\u t
呢?这可能是因为时钟信号不是一个很好定义的单位。您可以将其转换为秒,并以双精度打印:
time_in_seconds = (double)time_in_clock_ticks / (double)CLOCKS_PER_SEC;
printf("%g seconds", seconds);
CLOCKS_PER_SEC宏扩展为一个表达式,表示一秒钟内的时钟滴答数。据我所知,您的做法是最好的。除了
clock\t
可能是实型之外:
time\u t
和clock\u t
应为整数或实浮点型
C标准必须适应各种各样的体系结构,这使得除了内部时钟类型是算术型之外,无法做出任何进一步的保证 在大多数情况下,您对时间间隔感兴趣,因此我将时钟滴答声的差值转换为毫秒。
无符号长的
即使是32位,也足以表示将近50天的间隔,因此对于大多数情况,它应该足够大:
clock_t start;
clock_t end;
unsigned long millis = (end - start) * 1000 / CLOCKS_PER_SEC;
一种方法是使用
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;
}
似乎没有完美的方法。问题的根源在于
clock\t
可以是整数或浮点
时钟可以是浮点类型
至于POSIX(投票给他),7.23.1/3还说:
[clock_t]是能够表示时间的算术类型
和6.2.5/18:
整数和浮点类型统称为算术类型
该标准将算术类型定义为整数或浮点类型
如果要除以时钟每秒,请使用长双精度
clock()
的返回值是由实现定义的,从中获得标准含义的唯一方法是除以CLOCKS\u PER\u second
以找到秒数:
clock_t t0 = clock();
/* Work. */
clock_t t1 = clock();
printf("%Lf", (long double)(t1 - t0));
这已经足够好了,尽管还不够完美,但有以下两个原因:
- 浮点类型似乎没有类似于
:因此,如果明天出现更大的浮点类型,它可能会被使用并破坏您的实现intmax\u t
- 如果
是一个整数,则转换为float的定义很好,可以使用最接近的float。您可能会失去精度,但与绝对值相比,这并不重要,而且只会在大量时间内发生,例如,x86中的clock\t
是80位浮点值和64位有效值,即数百万年(以秒计)long int
unsigned long
是目前可能的最大标准整数类型:
#include <stdint.h>
printf("%ju", (uintmax_t)(clock_t)1);
- 将来可能会有一个更大的
- 该标准已经(对@fuzzxl的赞誉)并且
可能是其中之一clock\t
#include <stdint.h>
printf("%ju", (uintmax_t)(clock_t)1);
#包括
printf(“%ju”,(uintmax)(时钟)1);
uintmax\u t
保证具有机器上可能的最大整数大小
uintmax\u t
及其printf说明符%ju
是在c99中引入的,例如gcc实现了它们
作为奖励,这一次性解决了如何可靠地printf
整数类型的问题(不幸的是clock\u t
不一定如此)
如果是双精度的,会出现什么问题:
time_in_seconds = (double)time_in_clock_ticks / (double)CLOCKS_PER_SEC;
printf("%g seconds", seconds);
- 如果太大而无法放入整数,则表示行为未定义
- 远小于1,将四舍五入为0,您将看不到任何内容
double
是一个更好的主意:
在GNU/Linux和GNU/Hurd系统上,clock_t相当于long int,CLOCKS_PER_SEC是一个整数值。但在其他系统中,时钟和宏时钟每秒都可以是整数或浮点类型。如上例所示,将CPU时间值强制转换为双倍,可以确保算术和打印等操作正常、一致地工作,而不管底层表示是什么
在glibc 2.21中:
是clock\u t
:long int
- 将其设置为
\uu clock\t
- 将其设置为
\u时钟\u类型
- 将其设置为
\uuu SLONGWORD\u TYPE
- 将其设置为
long int
- 将其设置为
- Linux中的
是通过clock()
实现的:sys\u clock\u gettime
- 调用
\u时钟\u获取时间
- 调用SYSDEP\u GETTIME\u CPU
- 调用
,最终进行内联系统调用SYSCALL\u GETTIME
告诉我们它返回一个manclock\u gettime
,它在GCC中包含struct timespec
字段 因此,底层实现实际上返回整数long int
- 调用
uintmax\t
和%ju
的整数?那就是