1

次のようにして、time_tをin64_tに変換しようとしています。

time_t t = 1349388030;

私はAPIを持っています。

SomeObj.setValue(const int64_t)            // Sets the value of SomeObj to the passed argument
SomeObj.getValue(int64_t & value) const    // Returns the value

次に、以下を実行します。

SomeObj.setValue(t)
int64_t tt;
SomeObj.getValue(tt)
assert (tt == t)                           // Fails where tt = 109726776

誰かが適切な鋳造手順を手伝ってもらえますか?

編集:

set_valueを使用していた方法のコードのバグでした

4

3 に答える 3

4

ある整数型から別の整数型へのキャストについて心配しなければならない3つのケースがあります。

  1. 大きな整数から小さな整数にキャストします。私はsizeof(int64_t) >= sizeof(time_t)それが問題になることはないはずだと合理的に確信しています。
  2. 符号なし型を符号付き型にキャストしましたが、値が符号付き型の範囲外です。1349388030は2^31未満であるため、これもありそうにありません。
  3. 符号付き型を符号なし型にキャストすると、値は負になります。ここでは適用されません。

キャスティングに問題はないと思います。

于 2012-10-04T22:31:02.310 に答える
2

あなたが言ったことから、SomeObjは実際には時間が何であるかを気にしない、それはあなたが時間を保存する必要がある単なるストレージコンテナであると仮定しています。また、あなたのユースケースでは、あなたが保存するフォーマットが何であれ、あなたの時間はポータブルである必要はありません、そして保存された時間はそれらが生成されたのと同じシステムで常に使用されます。これらの仮定のいずれかが当てはまらない場合、キャストは問題の適切な解決策ではありません(そして、以下でより適切な解決策について説明します。についての説明を参照してくださいlocaltime())。

time_t内に値を格納するにはint64_t変数、もちろんsizeof(time_t)はsizeof(int64_t)以下でなければならないので、コードはそのためのアサーションチェックを行う必要があります。これで、time_tをint64_tに割り当てることはできません(すべてのシステムではなく、ほとんどのシステムで問題なく機能します)。time_tが浮動小数点型の場合、変換時と変換時に精度が低下する可能性があるためです。 time_tに戻ると、同じ値ではない可能性があります(ただし、正しい値に「近い」場合があります)。重要なのは、移植可能なコードの場合、time_t値の形式について何も仮定できないということです。ここで繰り返しますが、以下のコードは移植可能ですが、ソリューションはそれ自体が移植可能な時間値を生成しません。つまり、あるシステムでtime_t値を生成し、SomeObjがその値を別の「システム」に送信する場合 (同じプロセッサ上でも、別のコンパイラによってコンパイルされた場合でも)他のシステムで解釈する場合、他のシステムは値を同じように解釈する場合としない場合があります。そのためには、time_tを離散数に変換する必要があります。localtime()または、その構造を他のシステムにlocaltime_r()転送し、を介してそのシステムのtime_t形式に変換します。mktime()

いずれにせよ、解釈に依存しない方法でtime_t値をuint64_tに詰め込むには、time_t値の場所からビットをuint64_tとして読み取る必要があります。time_tがuint64_tほど広くない場合は、余分なビットを読み込みますが、それは問題ではありません。それらのビットは「ドントケア」ビットです。次に、そのuint64_tからtime_t値を読み取るには、uint64_tの場所からtime_tとしてビットを読み取る必要があります。つまり、ソース変数のアドレスを取得し、それを宛先タイプのポインターとしてキャストしてから、逆参照します。タイプのサイズが一致しない場合は、宛先変数に余分なガベージビットを読み込むか、とにかくガベージビットであったと思われるビットを失います。これがコードでそれを行う方法です...

#include <time.h>
#include <assert.h>

struct SomeClass
{
    int64_t i64;
    void setValue(const int64_t v) { i64 = v; }
    void getValue(int64_t& v) const { v = i64; }
};

#if 0 // Set to 1 for C style casting, or 0 for C++ style casting.

    int main()
    {
        assert (sizeof(int64_t) >= sizeof(time_t));
        // ...fundamental, otherwise nothing else has any hope of working

        SomeClass SomeObj;

        time_t t = 1349388030;
        int64_t i = *((int64_t*)&t);
        SomeObj.setValue(i);

        int64_t ii;
        time_t tt;
        SomeObj.getValue(ii);
        tt = *((time_t*)&ii);

        assert (tt == t);
    }

#else

    int main()
    {
        assert (sizeof(int64_t) >= sizeof(time_t));
        // ...fundamental, otherwise nothing else has any hope of working

        SomeClass SomeObj;

        time_t t = 1349388030;
        int64_t i = *reinterpret_cast<int64_t*>(&t);
        SomeObj.setValue(i);

        int64_t ii;
        time_t tt;
        SomeObj.getValue(ii);
        tt = *reinterpret_cast<time_t*>(&ii);

        assert (tt == t);
    }

#endif
于 2012-10-05T15:13:04.673 に答える
0

コードに問題はありません。一部のプラットフォームtime_tでは、すでにint64_tです。あなたの問題は他のところにあると思います。中身はSomeObj

于 2012-10-04T22:21:41.347 に答える