是否可以将
float
从大端转换为小端?我有来自 PowerPC 平台的大端值,我通过 TCP 将其发送到 Windows 进程(小端值)。这个值是一个 float
,但是当我 memcpy
将该值转换为 Win32 float 类型,然后对该值调用 _byteswap_ulong
时,我总是得到 0.0000?
我做错了什么?
简单地反转四个字节就可以了
float ReverseFloat( const float inFloat )
{
float retVal;
char *floatToConvert = ( char* ) & inFloat;
char *returnFloat = ( char* ) & retVal;
// swap the bytes into a temporary buffer
returnFloat[0] = floatToConvert[3];
returnFloat[1] = floatToConvert[2];
returnFloat[2] = floatToConvert[1];
returnFloat[3] = floatToConvert[0];
return retVal;
}
这是一个可以反转任何类型的字节顺序的函数。
template <typename T>
T bswap(T val) {
T retVal;
char *pVal = (char*) &val;
char *pRetVal = (char*)&retVal;
int size = sizeof(T);
for(int i=0; i<size; i++) {
pRetVal[size-1-i] = pVal[i];
}
return retVal;
}
我很久以前就发现了大致类似的东西。这对于笑很有好处,但摄入后果自负。我什至还没有编译它:
void * endian_swap(void * arg)
{
unsigned int n = *((int*)arg);
n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00);
n = ((n >> 16) & 0x0000ffff) | ((n << 16) & 0xffff0000);
*arg = n;
return arg;
}
进行字节交换的一种优雅方法是使用联合:
float big2little (float f)
{
union
{
float f;
char b[4];
} src, dst;
src.f = f;
dst.b[3] = src.b[0];
dst.b[2] = src.b[1];
dst.b[1] = src.b[2];
dst.b[0] = src.b[3];
return dst.f;
}
按照 jjmerelo 建议编写一个循环,更通用的解决方案可能是:
typedef float number_t;
#define NUMBER_SIZE sizeof(number_t)
number_t big2little (number_t n)
{
union
{
number_t n;
char b[NUMBER_SIZE];
} src, dst;
src.n = n;
for (size_t i=0; i<NUMBER_SIZE; i++)
dst.b[i] = src.b[NUMBER_SIZE-1 - i];
return dst.n;
}
不要将数据直接memcpy到float类型中。将其保留为 char 数据,交换字节,然后然后 将其视为浮点数。
来自 SDL_endian.h,略有改动:
std::uint32_t Swap32(std::uint32_t x)
{
return static_cast<std::uint32_t>((x << 24) | ((x << 8) & 0x00FF0000) |
((x >> 8) & 0x0000FF00) | (x >> 24));
}
float SwapFloat(float x)
{
union
{
float f;
std::uint32_t ui32;
} swapper;
swapper.f = x;
swapper.ui32 = Swap32(swapper.ui32);
return swapper.f;
}
使用ntoa和相关函数从网络到主机以及从主机到网络的转换可能会更容易......它的优点是可移植的。 这里是一篇文章的链接,解释了如何执行此操作。
这个值是一个浮点数,但是当我将值“memcpy”到win32浮点类型中,然后对该值调用
时,我总是得到0.0000?_byteswap_ulong
这应该有效。你能发布你的代码吗?
但是,如果您关心性能(也许您不关心,在这种情况下您可以忽略其余部分),应该可以避免 memcpy,方法是直接将其加载到目标位置并交换那里的字节,或者使用swap 在复制时进行交换。
在某些情况下,尤其是在 modbus 上:浮点数的网络字节顺序是:
nfloat[0] = float[1]
nfloat[1] = float[0]
nfloat[2] = float[3]
nfloat[3] = float[2]
@morteza 和 @AnotherParker 已经提到了 Boost 库,指出对
float
的支持已被删除。然而,自从他们写下评论后,它就被添加回库的一个子集中。
使用 Boost.Endian 转换函数,版本 1.77.0 当我写这个答案时,你可以执行以下操作:
float input = /* some value */;
float reversed = input;
boost::endian::endian_reverse_inplace(reversed);
查看常见问题解答以了解为什么支持被删除然后部分添加回来(主要是因为反转的
float
可能不再有效)并此处了解支持历史记录。
快速破解:
#define FBIT32_REVERSE(val) htonl(*(long*) &val)