How do I reinterpret data through a different type? (type punning confusion)

前端 未结 3 1126
南笙
南笙 2020-12-19 10:47
#include 

int main(int argc, char * argv[])
{
    int a = 0x3f800000;

    std::cout << a << std::endl;

    static_assert(sizeof(float)         


        
3条回答
  •  情深已故
    2020-12-19 11:11

    As you've found out, reinterpret_cast can't be used for type punning

    • Is reinterpret_cast type punning actually undefined behavior?
    • Is reinterpret_cast mostly useless?

    Since C++20 you'll have a safe way for type punning via std::bit_cast

    uint32_t bit_pattern = 0x3f800000U;
    constexpr auto f = std::bit_cast(bit_pattern);
    

    At the moment std::bit_cast is only supported by MSVC

    While waiting for others to implement that, if you're using Clang you can try __builtin_bit_cast. Just cast it like this

    float f = __builtin_bit_cast(float, bit_pattern);
    

    See demo on Godbolt


    In other compilers or older C++ standards the only way you can do is via a memcpy

    However many compilers have implementation-specific way to do type punning, or implementation-specific behavior regarding type punning. For example in GCC you can use __attribute__((__may_alias__))

    union Float
    {
        float __attribute__((__may_alias__)) f;
        uint32_t __attribute__((__may_alias__)) u;
    };
    
    uint32_t getFloatBits(float v)
    {
        Float F;
        F.f = v;
        return F.u;
    }
    

    ICC and Clang also support that attribute. See demo

提交回复
热议问题