我正在尝试从浮点数中提取位而不调用未定义的行为。这是我的第一次尝试:

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;
}

最佳答案

真正避免任何问题的唯一方法就是内存。

unsigned int FloatToInt( float f )
{
   static_assert( sizeof( float ) == sizeof( unsigned int ), "Sizes must match" );
   unsigned int ret;
   memcpy( &ret, &f, sizeof( float ) );
   return ret;
}

由于您存储的是固定数量,因此编译器会对其进行优化。

也就是说,联合方法得到了广泛的支持。

关于c++ - float 位和严格的混叠,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4328342/

10-11 19:20