我想获取double
变量的最重要的32位字。
我知道double
长度为8个字节,我希望我的函数返回unsigned long
,它将保存double的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);
}
答案 0 :(得分:4)
将value
类型转换为unsigned long long
只需将其截断为整数,不会在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;
}
答案 1 :(得分: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未定义的,但它是相当普遍的,并且是在编译器开始采用它之后,在21世纪初避免严格别名问题的推荐方法之一。请在此处查看较长时间的内容:Understanding Strict Aliasing
答案 2 :(得分:0)
像这样:
uint32_t msw(double d);
{
uint32_t n[2];
memcpy(n, &d, 8);
return n[0];
}
根据字节顺序和其他平台细节,您的里程可能会有所不同。