我试图从浮点数中提取位,而不会引发未定义的行为。这是我的第一次尝试:
unsigned foo(float x)
{
unsigned* u = (unsigned*)&x;
return *u;
}
据我理解,由于严格的别名规则,这并不保证能够正常工作,对吗?如果我使用一个字符指针进行中间步骤,它是否有效?
unsigned bar(float x)
{
char* c = (char*)&x;
unsigned* u = (unsigned*)c;
return *u;
}
还是需要我自己提取每个字节吗?
unsigned baz(float x)
{
unsigned char* c = (unsigned char*)&x;
return c[0] | c[1] << 8 | c[2] << 16 | c[3] << 24;
}
当然,这种方法有依赖于大小端的缺点,但我可以接受。
使用联合体的技巧肯定是未定义行为,对吗?
unsigned uni(float x)
{
union { float f; unsigned u; };
f = x;
return u;
}
为了完整起见,这里提供了 foo
的参考版本。也是未定义行为,对吧?
unsigned ref(float x)
{
return (unsigned&)x;
}
那么,从一个浮点数中提取位是否可能(当然,假设两者都是32位宽)?编辑:这里是Goz提出的
memcpy
版本。由于许多编译器尚不支持static_assert
,因此我用一些模板元编程替换了static_assert
。template <bool, typename T>
struct requirement;
template <typename T>
struct requirement<true, T>
{
typedef T type;
};
unsigned bits(float x)
{
requirement<sizeof(unsigned)==sizeof(float), unsigned>::type u;
memcpy(&u, &x, sizeof u);
return u;
}