time() / difftime() / clock()
| 対応: | C89(1989) |
|---|
現在時刻や経過時間を取得するための関数・型です。『<time.h>』に定義されており、タイムスタンプの記録・処理時間の計測・日時の計算などに使われます。
構文
// 現在のカレンダー時刻を返します。 // 戻り値: 現在時刻を表す time_t 値(エポックからの秒数)。失敗時は (time_t)(-1)。 // t が NULL でなければ *t にも結果を格納します。 time_t time(time_t *t); // 2つの time_t 値の差を秒単位で返します。 // 戻り値: time1 - time0 の差(double 型の秒数)。 double difftime(time_t time1, time_t time0); // プログラムが使用したプロセッサ時間を返します。 // 戻り値: clock_t 値。CLOCKS_PER_SEC で割ると秒単位になります。 clock_t clock(void);
型・定数一覧
| 名前 | 種別 | 概要 |
|---|---|---|
| time_t | 型 | カレンダー時刻を表す算術型です。通常は 1970年1月1日 00:00:00 UTC(Unixエポック)からの秒数を保持します。 |
| clock_t | 型 | プロセッサ時間を表す算術型です。clock() の戻り値を CLOCKS_PER_SEC で割ると秒単位になります。 |
| CLOCKS_PER_SEC | 定数 | clock() の戻り値を秒に変換するための定数です(通常は 1000000)。 |
| time() | 関数 | 現在のカレンダー時刻(エポックからの秒数)を返します。 |
| difftime() | 関数 | 2つの time_t の差を秒単位の double で返します。 |
| clock() | 関数 | プログラム起動からのプロセッサ時間を返します。 |
サンプルコード
sample_time_difftime_clock.c
#include <stdio.h>
#include <time.h>
/* volatile を使って最適化を防ぎます。 */
static void heavy_work(void) {
volatile long sum = 0;
for (long i = 0; i < 50000000L; i++) {
sum += i;
}
}
int main(void) {
time_t now = time(NULL);
printf("UNIXタイムスタンプ: %ld\n", (long)now);
/* difftime で wall clock 時間を計測します。 */
time_t start_cal = time(NULL);
heavy_work();
time_t end_cal = time(NULL);
double elapsed_sec = difftime(end_cal, start_cal);
printf("wall clock 経過時間: %.0f 秒\n", elapsed_sec);
/* clock() でCPU処理時間を計測します。 */
clock_t cpu_start = clock();
heavy_work();
clock_t cpu_end = clock();
double cpu_sec = (double)(cpu_end - cpu_start) / CLOCKS_PER_SEC;
printf("CPU処理時間: %.4f 秒\n", cpu_sec);
return 0;
}
コンパイルして実行すると次のようになります。
gcc sample_time_difftime_clock.c -o sample_time_difftime_clock ./sample_time_difftime_clock UNIXタイムスタンプ: 1743379805 wall clock 経過時間: 0 秒 CPU処理時間: 0.0823 秒
タイムスタンプをログに記録する
ファイル処理や通信の開始・終了時刻を time() で記録するパターンです。difftime() で経過秒数を求められます。
time_log_session.c
#include <stdio.h>
#include <time.h>
/* 処理を模擬するダミー関数です。 */
static void process_data(void) {
volatile long x = 0;
for (long i = 0; i < 10000000L; i++) { x += i; }
}
int main(void) {
time_t session_start = time(NULL);
printf("処理開始: タイムスタンプ = %ld\n", (long)session_start);
process_data();
process_data();
time_t session_end = time(NULL);
double total = difftime(session_end, session_start);
printf("処理終了: タイムスタンプ = %ld\n", (long)session_end);
printf("合計経過時間: %.0f 秒\n", total);
/* clock() でCPU時間も併記します。 */
clock_t t0 = clock();
process_data();
clock_t t1 = clock();
printf("CPU時間(1回分): %.4f 秒\n", (double)(t1 - t0) / CLOCKS_PER_SEC);
return 0;
}
コンパイルして実行すると次のようになります。
gcc time_log_session.c -o time_log_session ./time_log_session 処理開始: タイムスタンプ = 1743379805 処理終了: タイムスタンプ = 1743379805 合計経過時間: 0 秒 CPU時間(1回分): 0.0165 秒
よくあるミス
よくあるミス: time_t を直接減算する
time_t の内部型は環境によって異なります。直接引き算するより difftime() を使う方が移植性が高くなります。
time_subtract_ng.c
#include <stdio.h>
#include <time.h>
int main(void) {
time_t t1 = time(NULL);
volatile long x = 0;
for (long i = 0; i < 30000000L; i++) { x += i; }
time_t t2 = time(NULL);
/* NG: time_t の差を直接 double に代入(型依存) */
/* double ng = t2 - t1; */
/* OK: difftime() を使う(移植性が高い) */
double ok = difftime(t2, t1);
printf("経過時間: %.0f 秒\n", ok);
return 0;
}
修正後は次の通りです。
gcc time_subtract_ng.c -o time_subtract_ng ./time_subtract_ng 経過時間: 0 秒
概要
『time()』が返す『time_t』はエポック(1970年1月1日 00:00:00 UTC)からの秒数です。2つの time_t の差を求めるとき、型の実装が環境によって異なるため、直接減算するより『difftime()』を使う方が移植性が高くなります。
『clock()』はウォールクロック(実際の経過時間)ではなく、プロセスが使用したCPU時間を返します。スリープ中や I/O 待ち時間は含まれません。そのため、ループ処理のパフォーマンス計測に向いています。
32ビット環境の time_t は 2038年1月19日にオーバーフローします(2038年問題)。64ビット環境では問題ありませんが、組み込みシステムなど32ビット環境向けのコードでは注意が必要です。
取得した time_t を人間が読める形式に変換するには『localtime() / gmtime()』や『strftime()』を使用してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。