現在、unsigned long long
への明示的なキャストを使用し、%llu
を使用して印刷していますが、size_t
には%z
指定子があるため、clock_t
を使用しないのはなぜですか持ってる?
マクロもありません。 x64システム(OSおよびCPU)でsize_t
の長さは8バイト(この場合でも%z
を提供している)と仮定できますが、clock_t
はどうですか?
完璧な方法はないようです。問題の根本は、_clock_t
_が整数または浮動小数点のいずれかである可能性があることです。
clock_tは浮動小数点型にすることができます
BastienLéonardがPOSIXについて 言及しているように(彼に賛成してください)、 C99 N1256 draft 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));
_
次の2つの理由から、これで十分ですが、完璧ではありません。
浮動小数点型の_intmax_t
_に類似していないようです: 実装の最大精度の浮動小数点データ型とそのprintf指定子を取得する方法? 浮動小数点型は明日公開され、使用されて実装が中断される可能性があります。
_clock_t
_が整数の場合、floatへのキャストは、可能な限り最も近いfloatを使用するように明確に定義されています。精度を失う可能性がありますが、絶対値と比較してそれほど重要ではなく、膨大な時間にのみ発生します。 x86の_long int
_は、64ビットの有効な80ビットの浮動小数点数で、数百万年単位で表されます。
整数であると仮定する場合は、%juとuintmax_tを使用します
_unsigned long long
_は現在、可能な最大の標準整数型です:
clock_t
_ is one of oneそのため、可能な限り最大の符号なし整数型に型キャストすることをお勧めします。
_#include <stdint.h>
printf("%ju", (uintmax_t)(clock_t)1);
_
_uintmax_t
_は、マシン上で可能な限り最大の整数サイズのサイズを持つことが保証されています。
_uintmax_t
_およびそのprintf指定子_%ju
_はc99で導入され、たとえばgccはそれらを実装しています。
おまけとして、これは整数型を確実にprintf
する方法に関する問題を一度解決します(残念ながら_clock_t
_の場合は必ずしもそうではありません)。
ダブルである場合、何がうまくいかない可能性があります:
これらの結果は、整数から浮動小数点への変換よりもはるかに厳しいので、浮動小数点数を使用することをお勧めします。
glibc 2.21では整数です
マニュアルでは、double
を使用することをお勧めします。
GNU/LinuxおよびGNU/Hurdシステムでは、clock_tはlong intと同等で、CLOCKS_PER_SECは整数値です。しかし、他のシステムでは、clock_tとマクロCLOCKS_PER_SECの両方が整数型または浮動小数点型のいずれかです。上記の例のように、CPU時間の値を2倍にキャストすると、基になる表現が何であっても、算術演算や印刷などの操作が適切かつ一貫して機能することが保証されます。
Glibc 2.21の場合:
_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
_は、GCCで_struct timespec
_フィールドを含む_long int
_を返すことを示します。
したがって、基礎となる実装は実際に整数を返します。
こちらもご覧ください
私の知る限り、あなたのやり方は最高です。それ以外で clock_t
は実数型の場合があります。
time_t
およびclock_t
は整数型または実浮動型でなければなりません。
http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/types.h.html
これはおそらく、クロック刻みが非常に明確な単位ではないためです。秒に変換して、倍精度で印刷できます。
time_in_seconds = (double)time_in_clock_ticks / (double)CLOCKS_PER_SEC;
printf("%g seconds", seconds);
CLOCKS_PER_SECマクロは、1秒のクロックティック数を表す式に展開されます。
C規格は、多種多様なアーキテクチャに対応する必要があり、内部クロックタイプが算術であることを除いて、それ以上の保証を行うことはできません。
ほとんどの場合、時間間隔に関心があるため、クロックティックの差をミリ秒に変換します。 unsigned long
は、32ビットであっても50日近くの間隔を表すのに十分な大きさなので、ほとんどの場合に十分な大きさである必要があります。
clock_t start;
clock_t end;
unsigned long millis = (end - start) * 1000 / CLOCKS_PER_SEC;
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;
}