閉じる

C言語のdifftimeで時刻差(秒)を計算する方法と実例

時刻と時刻の差を「秒」で知りたい場面は、処理時間の測定やタイムアウト判定など、実務でも学習でもたびたび登場します。

C言語には時刻差を安全かつ移植性高く計算できるdifftime関数が用意されています。

本記事ではdifftimeの基礎から具体例、注意点までを初心者向けに丁寧に解説します

C言語のdifftimeとは?

時刻差(秒)を計算する標準関数

difftimeは2つのtime_t値の差を秒単位で返す、C標準ライブラリの関数です

標準に含まれるため、OSやコンパイラが異なっても同じインターフェースで利用できます。

内部では実装依存のtime_tを安全に扱い、符号やビット幅の違いによる問題を避けるよう設計されています。

役割の概要

「終点の時刻 − 始点の時刻」を秒で返します。

秒数は実数のdoubleで表され、通常は整数秒になりますが、環境によっては小数部を持ち得ます。

演算はdifftime(end, start)のように、終点を第1引数、始点を第2引数に渡します

いつ使うか

処理の経過時間を測る、2つのログ時刻の差を比較する、一定時間経過を待つといった用途で使います。

「秒」で比較できればよい場面に最適です。

戻り値はdouble型

戻り値はdouble型です

これは、非常に大きい時刻差を扱えるようにするためと、実装によってはtime_tが非整数を表す可能性を考慮したためです。

なぜ整数ではないのか

整数にすると表現できる範囲が狭まり、また中間計算でのオーバーフロー検出が難しくなります

doubleなら広い範囲を扱え、丸め処理も柔軟に行えます

丸めと表示の考え方

表示の際はprintf("%.0f", diff)のように小数部を抑えて出力したり、必要に応じて%.3fで小数点以下を表示します。

整数秒として使うなら、丸めや切り捨ての方針をあらかじめ決めておきましょう

必要なヘッダーは<time.h>

#include <time.h>が必須です

また、結果を表示するにはprintfを使うため#include <stdio.h>も併用します。

インクルード例

C言語
#include <stdio.h>  // printfなどの入出力
#include <time.h>   // time_t, time, difftime

difftimeの基本的な使い方

関数プロトタイプと引数

difftimeのプロトタイプは次の通りです

C言語
// time.h より
double difftime(time_t time1, time_t time0);
// 戻り値: time1 - time0 を秒で表した double

引数の順序に注意

第1引数が「後の時刻」(終点)、第2引数が「前の時刻」(始点)です

順序を逆にすると負の値が返ります。

2つのtime_tを渡して秒差を得る

典型的にはtime(NULL)で現在時刻を取り、処理の前後で2回取得してdifftimeに渡します

差が秒単位で得られるため、単純な経過時間計測に適しています。

例の流れ

1回目のtimeで始点を取得し、処理を行い、2回目のtimeで終点を取得します。

この2つをdifftime(end, start)に渡せば秒差が求まります

結果の表示

表示はprintfで行います

必要に応じて小数点以下の桁数を調整します。

フォーマット指定の実例

C言語
#include <stdio.h>
#include <time.h>

int main(void) {
    time_t t0 = time(NULL);
    time_t t1 = t0 + 123;           // 123秒後の時刻を仮想的に用意
    double diff = difftime(t1, t0); // 秒差は123.0になる想定

    // 小数なしで表示(四捨五入)
    printf("四捨五入: %.0f 秒\n", diff);

    // 小数点以下3桁まで表示
    printf("小数あり: %.3f 秒\n", diff);

    // 切り捨てて整数秒として扱う(明示的にキャスト)
    printf("切り捨て: %lld 秒\n", (long long)diff);

    return 0;
}
実行結果
四捨五入: 123 秒
小数あり: 123.000 秒
切り捨て: 123 秒

丸め方は仕様や要件に合わせて統一しましょう

切り捨てはキャスト、四捨五入は%.0fllround(要math.h)などの手段があります。

difftimeの実例コード

2つのtime_tの秒差を表示

まずは2つのtime_tの差をそのまま表示する最小例です

ここでは現在時刻に90秒を足して、90秒差が出ることを確認します。

C言語
#include <stdio.h>
#include <time.h>

int main(void) {
    // 現在のUNIX時刻(秒)を取得
    time_t start = time(NULL);

    // デモ用に "90秒後" の時刻を作る
    // 実際には処理を行った後に time(NULL) を再度呼びます
    time_t end = start + 90;

    // 秒差を計算
    double diff = difftime(end, start);

    // 結果を表示(小数なし)
    printf("2つの時刻の差は %.0f 秒です。\n", diff);

    return 0;
}
実行結果
2つの時刻の差は 90 秒です。

実務ではendに加算せず、処理の前後でそれぞれtime(NULL)を呼びます

経過時間(秒)を測るシンプルな例

次は、処理の経過時間を実際に測る例です

ここでは分かりやすさのため、difftime自身を使って約2秒待つ簡単なループを利用します(いわゆるビジーウェイト。デモ用であり実務では非推奨)。

C言語
#include <stdio.h>
#include <time.h>

int main(void) {
    // 計測開始時刻
    time_t start = time(NULL);

    // おおよそ2秒経過するまで待機(ビジーウェイト)
    // 実務では sleep や thrd_sleep などの待機APIを検討してください
    while (difftime(time(NULL), start) < 2.0) {
        // 何もしない(デモ用の待機)
    }

    // 計測終了時刻
    time_t end = time(NULL);

    // 経過秒を計算
    double elapsed = difftime(end, start);

    // 結果を表示
    printf("経過時間: %.0f 秒\n", elapsed);

    return 0;
}
実行結果
経過時間: 2 秒

経過時間の測定は「開始」「終了」「difftimeで差を取る」の3ステップが基本です

difftimeの注意点

time_tの直接の引き算を避ける理由

time_t同士を直接引き算するのは避け、必ずdifftimeを使いましょう

time_tは実装依存で、符号付きか符号なし、ビット幅などが環境で異なるため、単純な減算は思わぬ不具合の原因になります。

よくある落とし穴と影響

理由起こりうる問題
time_tの符号が実装依存負の差を扱えない環境で桁あふれや巨大値になる
ビット幅が実装依存(32/64bitなど)減算時にオーバーフローや符号反転を招く
中間計算の型が未定義になりやすい最終的なdoubleへの変換で誤った値になる

difftimeはこれらの違いを吸収するために用意された標準関数です

望ましい書き方の比較

C言語
// 悪い例(直接引き算): 実装によっては未定義動作や誤動作の可能性
// long long sec = end - start;

// 良い例: difftimeで安全に差分を得る
double sec = difftime(end, start);

負の値が返るケース

第1引数の時刻が第2引数より過去であれば、difftimeは負の値を返します

比較や方向判定に便利です。

簡単な確認例

C言語
#include <stdio.h>
#include <time.h>

int main(void) {
    time_t a = time(NULL);
    time_t b = a + 10; // aの10秒後

    // あえて順序を逆にして差を取る
    double d = difftime(a, b); // a - b = -10

    if (d < 0.0) {
        printf("aはbより %.0f 秒だけ過去です。\n", -d);
    } else {
        printf("aはbと同時刻か未来です。\n");
    }
    return 0;
}
実行結果
aはbより 10 秒だけ過去です。

順序を明確にし、負値が想定通りか常に意識しましょう

移植性と精度のポイント

difftimeは移植性を高めますが、精度や範囲には実装依存の側面があります

押さえておきたい事項

time_tの範囲: 32bit環境では2038年問題があり得ます。64bittime_tでは広い範囲を表せますが、そもそもtime_tに表現できない時刻は扱えません。

doubleの丸め: doubleは約15〜16桁の有効桁を持ちます。日常的な計測範囲では問題になりにくいですが、非常に大きな差(数十万年規模)では厳密な整数性が崩れる可能性があります。

サブ秒精度: 標準のtime関数は整数秒単位の現在時刻を返す実装が多く、difftimeの結果も通常は整数秒です。サブ秒(ミリ秒など)の精密計測が必要な場合は、別のAPI(例: POSIXのclock_gettime)の検討が必要です

まとめ

difftimeは、2つのtime_tの差を安全かつ移植性高く「秒」で得られる標準関数です

使い方はdifftime(end, start)とシンプルで、表示はprintf("%.0f")などで調整できます。

直接の引き算は避ける、負の値の扱いに注意する、精度や範囲の限界を理解する、といったポイントを押さえれば、初心者の方でも確実に経過時間や時刻差を扱えるようになります。

実務では要件に合わせて丸め方を決め、必要なら高精度の計時APIを併用してください。

この記事を書いた人
エーテリア編集部
エーテリア編集部

プログラミングの基礎をしっかり学びたい方向けに、C言語の基本文法から解説しています。ポインタやメモリ管理も少しずつ理解できるよう工夫しています。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!