C++ 将浮点值从大端转换为小端

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2782725/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 00:39:06  来源:igfitidea点击:

Converting float values from big endian to little endian

c++endianness

提问by Blade3

Is it possible to convert floats from big to little endian? I have a big endian value from a PowerPC platform that I am sendING via TCP to a Windows process (little endian). This value is a float, but when I memcpythe value into a Win32 float type and then call _byteswap_ulongon that value, I always get 0.0000?

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

What am I doing wrong?

我究竟做错了什么?

回答by Gregor Brandt

simply reverse the four bytes works

只需反转四个字节即可

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

回答by Sniggerfardimungus

I found something roughly like this a long time ago. It was good for a laugh, but ingest at your own peril. I've not even compiled it:

很久以前我发现了大致类似的东西。这很好,但要自担风险。我什至没有编译它:

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

回答by Benjamin

Here is a function can reverse byte order of any type.

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

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

回答by jscharf

Don't memcpy the data directly into a float type. Keep it as chardata, swap the bytes and thentreat it as a float.

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

回答by Antonio Ca?as Vargas

An elegant way to do the byte exchange is to use a union:

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

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

Following jjmerelo's recommendation to write a loop, a more generic solution could be:

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

回答by t0mm13b

It might be easier to use the ntoa and related functions to convert from network to host and from host to network..the advantage it would be portable. Hereis a link to an article that explains how to do this.

使用 ntoa 和相关功能从网络到主机以及从主机到网络的转换可能更容易......它的优点是可移植。是一篇解释如何执行此操作的文章的链接。

回答by infval

From SDL_endian.hwith slight changes:

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

回答by Suma

This value is a float, but when I "memcpy" the value into a win32 float type and then call _byteswap_ulongon that value, I always get 0.0000?

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

This should work. Can you post the code you have?

这应该有效。你能把你的代码贴出来吗?

However, if you care for performance (perhaps you do not, in that case you can ignore the rest), it should be possible to avoid memcpy, either by directly loading it into the target location and swapping the bytes there, or using a swap which does the swapping while copying.

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

回答by steppenwolf

A nice way to get to the value is to use struct.pack/unpack.
You can use the ">" character in the format to indicate that the bytes are in reverse (big endian).

获取值的一个好方法是使用 struct.pack/unpack。
您可以在格式中使用“>”字符来指示字节是反向的(大端)。

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

output:

输出:

(200,)
(200,)