ソフトウェアエンジニア現役続行

雑多なことを綴ります

localtime()は同じポインタを見ている

C言語でlocaltime()を使っていてハマりました。以下のようなケースで、です。

#include 
#include 

int main (void)
{
    time_t t1, t2;
    struct tm *tm1, *tm2;

    t1 = time(NULL);        // 現在時刻を取得
    t2 = t1 + 24 * 60 * 60; // 24時間後の時刻を取得

    tm1 = localtime(&t1);   // 現在時刻をtm構造体で取得
    tm2 = localtime(&t2);   // 24時間後の時刻をtm構造体で取得

    // それぞれの時刻を表示
    printf("tm1:%04d/%02d/%02d %02d:%02d:%02d\n",
           tm1->tm_year+1900, tm1->tm_mon+1, tm1->tm_mday,
           tm1->tm_hour, tm1->tm_min, tm1->tm_sec);
    printf("tm2:%04d/%02d/%02d %02d:%02d:%02d\n",
           tm2->tm_year+1900, tm2->tm_mon+1, tm2->tm_mday,
           tm2->tm_hour, tm2->tm_min, tm2->tm_sec);

    return 0;
}

上記プログラムは、現在時刻と24時間後の時刻がそれぞれ標準出力に表示されることを期待して作りました。しかし、実際にこれをコンパイルして実行してみると・・・

tm1:2009/06/26 23:34:18
tm2:2009/06/26 23:34:18

このように両方とも24時間後の時刻が表示されてしまいます・・・。

glibcのlocaltime()の実装を見て、原因が理解できました。glibcの入手方法は以前書いたglibcの実装を見る方法2を参照してください。

glibc/time/localtime.cを見ると、

/* The C Standard says that localtime and gmtime return the same pointer.  */
struct tm _tmbuf;

・・・(省略)・・・

/* Return the `struct tm' representation of *T in local time.  */
struct tm *
localtime (t)
     const time_t *t;
{
  return __tz_convert (t, 1, &_tmbuf);
}

となっていました。

つまり、localtime()はstruct tm型のポインタを返し、localtime()が呼ばれるたびに、同じポインタを返していました。

なぜこのような実装になっているのか不明です・・・。

「C standards says ...」と、C標準のせいにしていますが、なぜC標準はこのような実装になっているのでしょうか。