1

変数の最上位 32 ビット ワードを取得したいと考えていdoubleます。

a の長さが 8 バイトであることはわかっており、関数の戻り値として、double の最上位 4 バイトを保持するdoublean を期待しています。unsigned long

unsigned long doublesmsw(double value);

int main()
{
  double d=54645654663905 ;
  unsigned long fin=doublesmsw(d);
  printf("%lu", fin );
  return 0;
}

unsigned long doublesmsw(double value)
{
  unsigned long long mask=0x00000000ffffffff ;
  return ((unsigned long long) value>>32 & mask);
}
4

3 に答える 3

4

への型キャストvalueunsigned long long単純に整数に切り捨てます。のメモリ表現は得られませ。代わりに使用してください:doubleunsigned long longmemcpy

unsigned long doublesmsw(double value)
{
    unsigned long r;
    memcpy(&r, &value, sizeof(r));
    // or memcpy(&r, (char *)&value + 4, sizeof(r));, depending on endianness
    return r;
}

または、示唆されているように、ターゲットアーキテクチャが整数と浮動小数点数に同じエンディアンを使用している場合 (ほとんどの場合):

unsigned long doublesmsw(double value)
{
    unsigned long long r;
    memcpy(&r, &value, sizeof(r));
    return r >> 32;
}
于 2013-05-23T11:32:49.447 に答える
2

値をキャストするだけでなく、メモリの同じ領域を参照する必要があります。C99 (またはそのあたり) で許可されているエイリアシングの最適化に従ってこれを行う 1 つの方法は、共用体を介してキャストすることです。

union doubleUll {
    double d;
    unsigned long long ull;
};

unsigned long doublesmsw(double value)
{
    union doubleUll u;
    u.d = value;
    return (u.ull >> 32) & mask;
}

...しかし、ケレックは正しいです。これは実際にはC99では定義されていませんが、かなり一般的であり、コンパイラによって採用され始めた後、2000年代初頭に厳密なエイリアシングの問題を回避する型をキャストする推奨される方法の1つでした. ここでより長い記事を参照してください:厳密なエイリアシングを理解する

于 2013-05-23T11:33:31.537 に答える
0

このような:

uint32_t msw(double d);
{
    uint32_t n[2];
    memcpy(n, &d, 8);
    return n[0];
}

マイレージは、エンディアンやその他のプラットフォームの仕様によって異なる場合があります。

于 2013-05-23T11:32:11.543 に答える