在c++ 14, c++ 17, c++ 20和不同的编译器中,是否有最好的方法来处理浮点数和整数之间的按位转换中的未定



在处理未定义行为、自动向量化(用于数组结构)和可移植性(clang、gcc、msvc、icc)方面,以下测试中哪种方式是最受欢迎的?

是否有另一种方法来做相同的操作?

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

例如,memcpy是否可以将浮点数组按位转换为整数数组?

  • trick1 (union):在ISO c++中未定义的行为,不像ISO C99。
    你提到的c++编译器支持它作为c++的扩展。

  • trick2 (std::memcpy)是c++ 20之前的最佳选择:以sizeof(int) == sizeof(float)为前提确定,但不像std::bit_cast那么简单。主流编译器可以有效地处理它,实际上不做任何额外的拷贝(有效地优化它),只要拷贝大小是单个基本类型并写入目标对象的所有字节。

  • trick3 (inlineasm):非标准;不可移植(既不是CPU拱也不是编译器)。严重阻碍优化,包括自动向量化。

  • trick4 (deref areinterpret_cast指针):在ISO c++中未定义的行为,并且在许多实际编译器(特别是GCC和Clang)中实践,除非您使用gcc -fno-strict-aliasing进行编译。


我推荐c++ 20std::bit_cast。它和memcpy一样高效,而且语法更清晰:

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

相关内容

  • 没有找到相关文章