1

我想获取double变量的最重要的 32 位字。

我知道 adouble有 8 个字节长,我希望作为我的函数的返回 anunsigned long将保存双精度的 4 个最高有效字节。

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简单地将其截断为整数,它不会产生in 的内存double表示unsigned long long。改用memcpy

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(或其附近)允许的别名优化之后执行此操作的一种方法是通过联合进行强制转换,例如

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

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

...但是 Kerrek 是正确的,这实际上是 C99 未定义的,但它相当普遍,并且是在 2000 年代初开始被编译器采用后避免严格别名问题的强制转换类型的推荐方法之一。在此处查看更长的文章:了解严格的别名

于 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 回答