2011-12-07 8 views
3

のファイルにタイムスタンプデータを読み込みと書き込み:C/C++:/usr/include/time.hからマルチアーキテクチャのサポート

/* Used by other time functions. */ 
struct tm 
{ 
int tm_sec;. . . /* Seconds..[0-60] (1 leap second) */ 
int tm_min;. . . /* Minutes..[0-59] */ 
int tm_hour;. . . /* Hours.. [0-23] */ 
int tm_mday;. . . /* Day... [1-31] */ 
int tm_mon;. . . /* Month.. [0-11] */ 
int tm_year;. . . /* Year.- 1900. */ 
int tm_wday;. . . /* Day of week..[0-6] */ 
int tm_yday;. . . /* Days in year.[0-365].*/ 
int tm_isdst;.. . /* DST... [-1/0/1]*/ 

#ifdef. __USE_BSD 
long int tm_gmtoff;. . /* Seconds east of UTC. */ 
__const char* tm_zone;./Timezone abbreviation. */ 
#else 
long int __tm_gmtoff;.. /* Seconds east of UTC. */ 
__const char* __tm_zone;./Timezone abbreviation. */ 
#endif 
}; 

あなたはファイルに、この構造を書きたい、あなたがしたい場合あなたのプログラムがそれを読み返してマルチアーチをサポートするようにしてください(つまり、32ビット版で64ビット版がそれを読み込みます)、システムごとに同じサイズであることを確認するためにいくつかのハックをしなければなりません。誰もアーキテクチャに依存しないタイムスタンプを保持するためのより良い方法を知っていますか?例えば、私は、time_tやstruct tmのような構造体をファイルに書き込んで、それをどのアーキテクチャでも読み込めるようにしたいと考えています。誰にもこれに関する経験やアドバイスはありますか? struct tmはC/C++でタイムスタンプを保存する最善の方法ですか?私は、この構造を使ってかなりのオーバーヘッドがあることを認識しています。

私は現在、以下に構造を再定義しています

//Force 32 bit format and space requirements 
struct tm32 
{ 
int tm_sec;. . . /* Seconds..[0-60] (1 leap second) */ 
int tm_min;. . . /* Minutes..[0-59] */ 
int tm_hour;. . . /* Hours.. [0-23] */ 
int tm_mday;. . . /* Day... [1-31] */ 
int tm_mon;. . . /* Month.. [0-11] */ 
int tm_year;. . . /* Year.- 1900. */ 
int tm_wday;. . . /* Day of week..[0-6] */ 
int tm_yday;. . . /* Days in year.[0-365].*/ 
int tm_isdst;.. . /* DST... [-1/0/1]*/ 

int tm_gmtoff; // this does nothing but hold space 
int tm_zone; // this does nothing but hold space 
}; 

私は構造体tmを操作するために使用している機能(はmktime()、時間()、のgmtime()、のstrftime())ので、 struct tm構造体の最後の2つのフィールドを見るようには見えないので、単純に整数をプレースホルダーとして使用して、サイズが常に同じになるようにします。しかし、私はまだ...これまでよりよい解決策を探しています

編集:私は上記の修正に使用されるint型はint32_tされたり、何でも固定幅のタイプを選択します。

答えて

5

は私の意見では、「ハッキング」としての資格はありません。 Blindly(恐らくパックされた)構造体をバイナリ形式で保存し、それを簡単に移植可能に読み戻すことを期待しています。

コンパイラはstructの "バイナリダンプ"に表示されるフィールド間にパディングを追加する可能性がありますが、完全にコンパイラに依存するため、プラットフォーム間の相互運用性には非常に悪いことがあります。

私はおそらく、構造のネイティブint分野のための合理的な精度を決定する32ビットを言うと、このような何か書くでしょう:単純に書く

void tm_serialize(FILE *out, const struct tm *tm) 
{ 
    int32_serialize(out, tm->tm_sec); 
    int32_serialize(out, tm->tm_min); 
    /* and so on */ 
} 

struct tm tm_deserialize(FILE *in) 
{ 
    struct tm tm; 
    tm.tm_sec = int32_deserialize(in); 
    tm.tm_min = int32_deserialize(in); 
    /* and so on */ 
    return tm; 
} 

場合は、もちろん、int32_serialize()int32_deserialize()を(と)十分に定義され、任意のプラットフォーム上でリードバックが容易で公知(例えばビッグエンディアンなど)形式の32ビット整数のバイナリ表現を読み取ります。

UPDATE:シリアライズ文字列はもちろんまったく同じ方法で行うことができ、1つの一般的なフォーマットは、即ち0で終了char配列Cのメモリ内のレイアウトと同じです。次に、あなただけの必要があるだろう:それはあまりにも多くのreadinで何かをオーバーフローしないように、ここで

void string_serialize(FILE *out, const char* string); 
int string_deserialize(FILE *in, char *string, size_t max); 

は、 string_deserialize()関数は、バッファサイズの制限を持っている必要があります。返り値が成功/失敗を示すと想像していたので、呼び出しコードは望みどおりの対策をとることができます。

コメント者は、実行時にintのフィールドの多くがその精度を必要としないことを指摘したため、スペースを最小限に抑えたシリアライゼーションを目的としていなかったため、シリアル化できるもっと小さなものに。それをやりたければ、int8_serialize()などの適切な機能を開発し、各フィールドに適切な機能を使用するのは簡単です。

+1

+1の最初の段落は – tobyodavies

+0

+1です。これは構造をシリアル化する一般的な方法です。 Nitpick:もしあなたがそれを詰めるつもりなら、それらのフィールドのほぼすべてのサイズは 'uint8_t'です。 'tm_year'はより多くの(または署名された型)を必要とし、' tm_gmtoff'はより大きく、署名する必要があります。 – derobert

+0

これは、整数フィールドの格納の問題を解決しますが、char *およびlong intメンバ(32ビットから64ビットの範囲である可能性があります)の標準固定幅フィールドを作成する必要があります。 – jkrez

0

ファイルをプラットフォームに完全に独立させるための確実な方法は、テキストファイルを使用することです。

変換された構造に<stdint.h>などのタイプを使用し、uint32_tなどのタイプを使用します。保存されたデータは、所望のプラットフォーム上で読み返すことができる方法で書かれていることを確認

+1

'uint32_t'は実際にはあなたを守りません。一つのアーキテクチャはビッグエンディアンで、もう一つはリトルエンディアンです。または、常に異なるパディングがある可能性があります。 – derobert

1

struct tmは通常、C/POSIXの時間関数で使用されます。あなたがそれらの機能によって許可された範囲外にそれを使用していないと仮定すると、明らかにいくつかの方法があります。

  • はそれを読むためにstrptime、それを書くためにstrftimeを使用しています。利点:出力データ(通常のISO形式など)で書かれた出力データを非常に分かりやすくしてtime_tに変換してから、バイナリまたはASCIIとして書き込むことができます。
  • mktime他の方向はlocaltimeまたはgmtimeです。利点:小、通常はバイナリの場合は4または8バイトです。 ASCIIではそれほど大きくありません。
+0

既存のデータ構造を変更することなく、まともなソリューションのようなstrftimeとstrptimeサウンドを使用する。私の使用がC/POSIXの時間関数の予想される使用以上になるケースは見当たりません。 Immaはこれを撃つ。 – jkrez

0

gettimeofday(2)エポックからの秒数とマイクロ秒を返します。時間がタイプtime_tであるため、32ビット(end of the world at 2038を配置する)か、それよりも大きくなる可能性がありますので、time_tuint64_tにキャストすることをおすすめします。 htobe64(3)などのツールを使用して、64ビット整数を指定されたバイト順で格納します。

関連する問題