Преобразование значений с плавающей точкой с прямым порядком байтов в младший - PullRequest
15 голосов
/ 06 мая 2010

Возможно ли преобразовать float s из старшего в младший порядок? У меня есть значение с прямым порядком байтов от платформы PowerPC, которое я отправляю через TCP процессу Windows (little-endian). Это значение float, но когда я memcpy значение в типе с плавающей запятой Win32 и затем вызываю _byteswap_ulong для этого значения, я всегда получаю 0,0000?

Что я делаю не так?

Ответы [ 8 ]

29 голосов
/ 06 мая 2010

просто поменяйте местами четыре байта

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;
}
6 голосов
/ 06 мая 2010

Я нашел что-то похожее на это давным-давно. Это было хорошо для смеха , но глотать на свой страх и риск. Я даже не скомпилировал это:

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;
}
4 голосов
/ 15 июля 2014

Здесь функция может изменить порядок байтов любого типа.

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;
}
2 голосов
/ 06 мая 2010

Не запоминайте данные напрямую в тип с плавающей запятой. Сохраните его как char data, поменяйте местами байты и затем обработайте его как число с плавающей запятой.

1 голос
/ 06 мая 2010

Может быть проще использовать ntoa и связанные функции для преобразования из сети в хост и из хоста в сеть ... преимущество в том, что он будет переносимым Здесь - ссылка на статью, объясняющую, как это сделать.

0 голосов
/ 11 ноября 2018

С 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;
}
0 голосов
/ 02 ноября 2010

Хороший способ получить значение - использовать 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)

Выход:

(200,)
(200,)
0 голосов
/ 14 мая 2010

Это значение является плавающим, но когда я "memcpy" передаю значение в тип с плавающей точкой win32 и затем вызываю _byteswap_ulong для этого значения, я всегда получаю 0,0000?

Это должно работать. Можете ли вы опубликовать свой код?

Однако, если вы заботитесь о производительности (возможно, нет, в этом случае вы можете игнорировать все остальное), можно избежать memcpy, либо напрямую загрузив его в целевое местоположение и поменяв там байты, либо используя своп, который делает обмен при копировании.

...