Is there a best way to deal with undefined behavior in bitwise conversion between floats and integers in C++14, C++17, C++20 and different compilers?

Which way in below tests is the most preferred in terms of dealing with undefined behavior, auto-vectorization (for struct of arrays) and portability (clang,gcc,msvc,icc)?

Is there another way of doing same operation?

#include <iostream>
#include <cstring>

union trick1
{
  float fvar;
  int ivar;
};

struct trick2
{
  float fvar;
  int ivar()
  {
      int result;
      std::memcpy(&result,&fvar,sizeof(float));
      return result;
  }
};

struct trick3
{
    float fvar;
    int ivar()
    {
        int result=0;
        asm ("mov %0,%0"
         : "=r" (result)
         : "0" (fvar));
        return result;
    }
     
};

struct trick4
{
    float fvar;
    int ivar()
    {
        int result;
        result = *reinterpret_cast<int*>(&fvar);
        return result;
    }
};

int main()
{
    trick1 test1;
    test1.fvar = 3.14f;
    // 1078523331
    std::cout<<test1.ivar<<std::endl;

    trick2 test2;
    test2.fvar = 3.14f;
    // 1078523331
    std::cout<<test2.ivar()<<std::endl;
    
    trick3 test3;
    test3.fvar = 3.14f;
    // 1078523331
    std::cout<<test3.ivar()<<std::endl;  
    
    trick4 test4;
    test4.fvar = 3.14f;
    // 1078523331
    std::cout<<test4.ivar()<<std::endl;  
    return 0;
}

For example, is memcpy ok for converting array of floats to array of integers bitwise?

>Solution :

trick1: Undefined behaviour.

trick2: Well defined with the precondition that sizeof(int) == sizeof(float), but not as simple as std::bit_cast

trick3: Non-standard; not portable.

trick4: Undefined behaviour.

I recommend std::bit_cast when applicable:

return std::bit_cast<int>(fvar);

Leave a Reply