studies

いろいろ勉強用備忘録的な感じ

時間を扱うライブラリ関数

引き続き、独習C++をやっている。
練習問題で、時間を扱うことが多い。

今までC言語でも時間を扱ったことがほとんどなかった。
C++というよりCの標準ライブラリ関数の勉強みたいになっている。

ctime(C言語ならtime.h)をかんたんにまとめる。

time_t型

ctimeをincludeすると、time_t型という型を使うことになる。
time_t型というと恐ろしい感じがするが、数値型である。
ほとんどの場合はlong型をtypedefしているだけらしい。
慣れないうちはtime_t = longと思っていいだろう。
私の環境でもtime_tはlongのようだ。

time関数 time_t time(time_t*)

引数の実体に現在時刻をセットする。
同時に現在時刻(暦時間)を返却する。
値を返すところが二つあって不思議な感じがする。
time_t now = time(NULL)
としても、別にsegmentation faultになったりはしない。
自分が使うとしたら、たぶんこういう使い方をするだろう。

私の環境では1970年1月1日0時0分からの秒数が返却される。
たいていの場合はそんな風になっているから、

    start = time(NULL);
        ;
        ;
    end = time(NULL);
    long passed_time = (long)end - start

という感じで、経過時間(秒単位)を求めることができる。
処理系依存の書き方になってしまうけど。

difftime関数 double difftime(time_t, time_t)

上の書き方を処理系依存から改良するためには、difftime関数を使う。
経過時間を秒単位で返してくれる。

ctime関数 char* ctime(time_t*)

引数を文字列に直して返却する。

clock関数 clock_t clock();

time関数が暦時間をtime_t型で返却するのに対して、clock関数は、プロセス開始からのCPU時間をclock_t型で返却する。
私の環境ではclock_t型もlong型であり、ミリ秒単位で返却される。
clock_t型を秒単位に直すために、CLOCKS_PER_SECマクロで割る必要がある。
この値が、私の環境では1000になっているというわけ。
これを使って、経過時間を求める場合は、

    start = clock();
        ;
        ;
    end = clock();
    double passed_time = 
        (double)(end - start) / CLOCKS_PER_SEC;

とする。

time関数とclock関数の違い

同じように経過時間を測れるように見えるが、大きく違う。
返却する値が、time関数は暦時間であり、clock関数はプロセッサ時間である。
プロセッサ時間というのは、プロセスがCPUを占有した時間である。
つまり、OSのタスクスケジューリングによっては、見た目ではとても時間が経過している(暦時間は進んでいる)のに、プロセスへのCPU資源の割り当てが少なく、プロセッサ時間はほとんど消費していない、というようなことが起こりうる。
この場合、time()関数で測った時間とclock()関数で測った時間には、違いが出ることになる。

実際、二つの環境(WindowsUbuntu)で次のコードを書いて動かしてみたら、だいぶ違う挙動をすることが観察できた。

#include <iostream>
#include <ctime>
using namespace std;

int main()
{
	
	// 何か入力してエンターキーを押すまでの時間を測る?
	time_t start = time(NULL);
	clock_t clock_start = clock();
	
	int a;
	cin >> a;
	
	time_t end = time(NULL);
	clock_t clock_end = clock();
	
	double clock_passed_time = (double) (clock_end - clock_start) / CLOCKS_PER_SEC;
        double passed_time = difftime(end, start);
	
	cout << "time()関数での計測時間\t" << passed_time << endl;
	cout << "clock()関数での計測時間\t" << clock_passed_time << endl;
	
	
	return 0;
}

Windowsではほぼ等しい値になったのに対し、Ubuntuではclock()関数での計測時間が著しく小さな数字になった。

面白い。