printf を使用して Clock_t を出力する正しい方法は何ですか?
質問
現在、明示的なキャストを使用して、 unsigned long long
そして使用して %llu
それを印刷するためですが、 size_t
持っています %z
指定子、なぜそうでないのか clock_t
持っていますか?
それ用のマクロすらありません。おそらく、x64 システム (OS と CPU) ではそう仮定できます。 size_t
長さは 8 バイトです (この場合でも、 %z
)、しかしどうでしょうか clock_t
?
解決
完璧な方法はないようです。問題の根本は、 clock_t
整数または浮動小数点のいずれかを指定できます。
Clock_t は浮動小数点型にすることができます
として バスティアン・レオナールが言及 POSIX の場合 (彼に賛成票を投じてください)、 C99 N1256 ドラフト 7.23.1/3 には次のようにも書かれています。
[lock_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));
これは完璧ではありませんが、次の 2 つの理由から十分です。
類似品はないようです
intmax_t
浮動小数点型の場合: 実装の最大精度の浮動小数点データ型とその printf 指定子を取得するにはどうすればよいですか? したがって、より大きな浮動小数点型が明日リリースされると、それが使用されて実装が壊れる可能性があります。もし
clock_t
が整数の場合、float へのキャストは、可能な限り最も近い float を使用するように明確に定義されています。精度が失われる可能性がありますが、絶対値に比べればそれほど問題ではなく、長時間にわたってのみ発生します。long int
x86 では、64 ビットの有効桁数を持つ 80 ビット浮動小数点であり、秒単位で数百万年を表します。
レモネードに賛成票を投じる 似たようなこと言ってた人。
整数であると仮定する場合は、%ju と uintmax_t を使用します。
それでも unsigned long long
現在可能な最大の標準整数型です。
- 将来的にはもっと大きなものも出るかもしれない
- すでに標準 より大きな実装定義型を明示的に許可します (@FUZxxl に敬意を表します)
clock_t
そのうちの1人かもしれない
したがって、可能な限り最大の符号なし整数型に型キャストすることが最善です。
#include <stdint.h>
printf("%ju", (uintmax_t)(clock_t)1);
uintmax_t
マシン上で可能な最大の整数サイズのサイズを持つことが保証されます。
uintmax_t
とその printf 指定子 %ju
c99 で導入され、たとえば gcc がそれらを実装します。
おまけに、これにより、確実に printf
整数型 (残念ながら必ずしもそうとは限りません) clock_t
).
double だった場合、何が問題になる可能性がありますか:
- 大きすぎて整数に収まらない場合、未定義の動作が発生します
- 1 よりはるかに小さい場合は 0 に丸められ、何も表示されません
これらの結果は整数から浮動小数点への変換よりもはるかに厳しいため、浮動小数点を使用する方が良い考えであると考えられます。
glibc 2.21 では整数です
マニュアルには、使用すると書かれています double
より良いアイデアです:
GNU/Linux および GNU/Hurd システムでは、lock_t は long int に相当し、CLOCKS_PER_SEC は整数値です。ただし、他のシステムでは、 Clock_t とマクロ CLOCKS_PER_SEC の両方が整数型または浮動小数点型のいずれかになります。上の例のように、CPU 時間の値を double にキャストすると、基礎となる表現が何であっても、算術演算や出力などの操作が適切かつ一貫して動作するようになります。
glibc 2.21 では:
clock_t
はlong int
:- 時間/時間.h に設定します
__clock_t
- ビット/タイプ.h に設定します
__CLOCK_T_TYPE
- ビット/タイプサイズ.h に設定します
__SLONGWORD_TYPE
- ビット/タイプ.h に設定します
long int
- 時間/時間.h に設定します
clock()
Linuxでは次のように実装されていますsys_clock_gettime
:- sysdeps/unix/sysv/linux/lock.c 電話
__clock_gettime
- sysdeps/unix/クロック_gettime.c 電話
SYSDEP_GETTIME_CPU
- sysdeps/unix/sysv/linux/lock_gettime.c 電話
SYSCALL_GETTIME
最終的にインライン システム コールを実行します
man clock_gettime
, 、を返すことがわかります。struct timespec
GCC には次のものが含まれますlong int
田畑。したがって、基礎となる実装は実際には整数を返します。
- sysdeps/unix/sysv/linux/lock.c 電話
こちらも参照
他のヒント
私の知る限りでは、あなたがやっている方法がベストです。その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マクロは、クロックの数秒間にマダニを表す式に展開されます。
C標準は、それが不可能内部クロック・タイプは、演算であるという事実とは別に、さらなる保証を行うことができるアーキテクチャの多種多様を収容しなければならない。
ほとんどの場合、あなたは時間間隔に興味ので、私はクロックの差がミリ秒に変換するダニと思います。 unsigned long
も、その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;
}