34

現在、明示的なキャストをunsigned long long使用して出力していますが、指定子がある%lluのに、なぜ指定子がないのですか?size_t%zclock_t

そのためのマクロすらありません。おそらく、x64 システム (OS と CPU)size_tでは長さが 8 バイトであると想定できます (この場合でも、提供されています) %zclock_t

4

5 に答える 5

31

完全な方法はないようです。問題の根本は、clock_t整数または浮動小数点のいずれかになる可能性があることです。

clock_t は浮動小数点型にすることができます

Bastien Léonard がPOSIX について言及しているように (彼に賛成票を投じてください)、C99 N1256 ドラフト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 を使用するように明確に定義されています。精度が失われる可能性がありますが、絶対値と比較するとそれほど重要ではなく、非常に長い時間しか発生しません。たとえばlong int、x86 では 80 ビットの float で 64 ビットが有意であり、これは秒単位で数百万年になります。

似たようなことを言ったレモネードに賛成票を投じてください。

整数だと思われる場合は、%ju と uintmax_t を使用してください

unsigned long long現在可能な最大の標準整数型ですが、

したがって、可能な限り最大の符号なし整数型に型キャストするのが最善です。

#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 システムでは、clock_t は long int と同等であり、CLOCKS_PER_SEC は整数値です。しかし、他のシステムでは、clock_t とマクロ CLOCKS_PER_SEC の両方が整数型または浮動小数点型のいずれかになります。上記の例のように、CPU 時間の値を double にキャストすると、基礎となる表現が何であれ、算術や印刷などの操作が適切かつ一貫して機能することが保証されます。

glibc 2.21 では:

こちらもご覧ください

于 2013-06-19T12:02:20.307 に答える
12

私の知る限り、あなたのやり方は最高です。ただしclock_t、実際の型である可能性があります。

time_tclock_t整数型または実数浮動小数点型でなければなりません。

http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/types.h.html

于 2009-07-04T23:14:23.987 に答える
11

おそらく、クロック ティックはあまり明確に定義された単位ではないためです。これを秒に変換して double として出力できます。

time_in_seconds = (double)time_in_clock_ticks / (double)CLOCKS_PER_SEC;
printf("%g seconds", seconds);

CLOCKS_PER_SEC マクロは、1 秒間のクロック ティック数を表す式に展開されます。

于 2009-07-04T23:12:30.763 に答える
4

C 標準は、さまざまなアーキテクチャに対応する必要があるため、内部クロック タイプが算術演算であるという事実を除けば、それ以上の保証を行うことはできません。

ほとんどの場合、時間間隔に関心があるので、クロック ティックの差をミリ秒に変換します。Anunsigned longは、32 ビットであっても 50 日近くの間隔を表すのに十分な大きさであるため、ほとんどの場合に十分な大きさである必要があります。

clock_t start;
clock_t end;
unsigned long millis = (end - start) * 1000 / CLOCKS_PER_SEC;
于 2009-07-05T00:19:13.017 に答える
1

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;
}
于 2009-12-22T11:23:01.663 に答える