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?
CodePudding user response:
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. Hinders optimisation.
trick4: Undefined behaviour.
I recommend std::bit_cast
when applicable:
return std::bit_cast<int>(fvar);