将浮点值从big endian转换为little endian

时间:2010-05-06 16:31:20

标签: c++ endianness

是否可以将float从大端转换为小端?我有一个来自PowerPC平台的大端值,我通过TCP发送到Windows进程(小端)。这个值是float,但当我memcpy将值转换为Win32 float类型然后在该值上调用_byteswap_ulong时,我总是得到0.0000?

我做错了什么?

10 个答案:

答案 0 :(得分:29)

简单地反转四个字节的工作

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

答案 1 :(得分:6)

我很久以前就发现了类似的东西。这对于来说是好事,但是你自己也要冒险。我甚至没有编译它:

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

答案 2 :(得分:4)

这是一个函数可以反转任何类型的字节顺序。

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

答案 3 :(得分:2)

不要将数据直接存入浮点类型。将其保留为 char 数据,交换字节,然后将其视为浮点数。

答案 4 :(得分:2)

进行字节交换的一种优雅方法是使用联合:

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

答案 5 :(得分:1)

使用ntoa和相关功能从网络转换为主机以及从主机转换为网络可能更容易。它具有便携性的优点。 Here是指向如何执行此操作的文章的链接。

答案 6 :(得分:0)

  

这个值是一个浮点数,但当我将值“memcpy”为win32 float类型然后在该值上调用_byteswap_ulong时,我总是得到0.0000?

这应该有效。你能发布你的代码吗?

但是,如果你关心性能(也许你不关心,在这种情况下你可以忽略其余的),应该可以通过直接将其加载到目标位置并在那里交换字节来避免memcpy,或者使用交换,在复制时进行交换。

答案 7 :(得分:0)

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

答案 8 :(得分:0)

在某些情况下,尤其是在modbus上:浮点数的网络字节顺序为:

nfloat[0] = float[1]
nfloat[1] = float[0]
nfloat[2] = float[3]
nfloat[3] = float[2]

答案 9 :(得分:-3)

获得该值的一个好方法是使用struct.pack / unpack 你可以使用“&gt;”格式中的字符,表示字节是反向的(大端)。

from struct import unpack, pack
sebytes = '\xc8\x00\x00\x00'
print unpack('l', sebytes)
bebytes = '\x00\x00\x00\xc8'
print unpack('>l', bebytes)

输出:

(200,)
(200,)