浮点位和严格的别名

float bits and strict aliasing(浮点位和严格的别名)
本文介绍了浮点位和严格的别名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在不调用未定义行为的情况下从浮点数中提取位.这是我的第一次尝试:

I am trying to extract the bits from a float without invoking undefined behavior. Here is my first attempt:

unsigned foo(float x)
{
    unsigned* u = (unsigned*)&x;
    return *u;
}

据我了解,由于严格的别名规则,这不能保证有效,对吧?如果使用字符指针进行中间步骤,它是否有效?

As I understand it, this is not guaranteed to work due to strict aliasing rules, right? Does it work if a take an intermediate step with a character pointer?

unsigned bar(float x)
{
    char* c = (char*)&x;
    unsigned* u = (unsigned*)c;
    return *u;
}

还是我必须自己提取单个字节?

Or do I have to extract the individual bytes myself?

unsigned baz(float x)
{
    unsigned char* c = (unsigned char*)&x;
    return c[0] | c[1] << 8 | c[2] << 16 | c[3] << 24;
}

当然,这有依赖字节序的缺点,但我可以忍受.

Of course this has the disadvantage of depending on endianness, but I could live with that.

union hack 绝对是未定义的行为,对吧?

The union hack is definitely undefined behavior, right?

unsigned uni(float x)
{
    union { float f; unsigned u; };
    f = x;
    return u;
}

为了完整起见,这里是 foo 的参考版本.也是未定义的行为,对吧?

Just for completeness, here is a reference version of foo. Also undefined behavior, right?

unsigned ref(float x)
{
    return (unsigned&)x;
}

那么,是否可以从浮点数中提取位(当然,假设两者都是 32 位宽)?

So, is it possible to extract the bits from a float (assuming both are 32 bits wide, of course)?

这里是 Goz 提出的 memcpy 版本.由于许多编译器还不支持 static_assert,我已将 static_assert 替换为一些模板元编程:

And here is the memcpy version as proposed by Goz. Since many compilers do not support static_assert yet, I have replaced static_assert with some template metaprogramming:

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

推荐答案

关于真正避免任何问题的唯一方法是 memcpy.

About the only way to truly avoid any issues is to memcpy.

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

因为你内存在一个固定的数量,编译器会优化它.

Because you are memcpying a fixed amount the compiler will optimise it out.

也就是说联合方法得到了非常广泛的支持.

That said the union method is VERY widely supported.

这篇关于浮点位和严格的别名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

Rising edge interrupt triggering multiple times on STM32 Nucleo(在STM32 Nucleo上多次触发上升沿中断)
How to use va_list correctly in a sequence of wrapper functions calls?(如何在一系列包装函数调用中正确使用 va_list?)
OpenGL Perspective Projection Clipping Polygon with Vertex Outside Frustum = Wrong texture mapping?(OpenGL透视投影裁剪多边形,顶点在视锥外=错误的纹理映射?)
How does one properly deserialize a byte array back into an object in C++?(如何正确地将字节数组反序列化回 C++ 中的对象?)
What free tiniest flash file system could you advice for embedded system?(您可以为嵌入式系统推荐什么免费的最小闪存文件系统?)
Volatile member variables vs. volatile object?(易失性成员变量与易失性对象?)