ИЗ Little endian в big-endian

184
07 марта 2019, 22:30

Нужно перевести число из Little endian в big-endian.. Дано изначально 32 битное число представленное в десятичном виде.. Нужно выдать конечное число, тоже в 10 виде.. Допустим 3496683923 в 16 системе будет выглядеть как D06B2993.. Делим по байтам: D0 6B 29 93.. Меняем местами относительно концов.. 93 29 6B D0. Собираем обратно все это дело 93296BD0 и переводим в 10 вид: 2468965328.

Если есть способ по проще, то можете пожалуйста объяснить? Есть набросок кода, который преобразует в 16 систему.. Но как от туда забрать эти данные и преобразовать в 10 сс, понятия не имею. (код не мой, не придирайтесь сильно)

#include <iostream>
#include <sstream>
#include <string.h>
using namespace std;
int main()
{ 
    string normal;
    int const Value = 3496683923;
    unsigned char const *pByte = (unsigned char const *)&Value;
    for (size_t i = 0; i < sizeof (Value); ++i)
    {
        cout  << hex<< static_cast<int>(pByte[i]) << endl;
    }
    cout << endl;
    return 0;
}
Answer 1

Методов много - функция ntohl, инструкция ассемблера bswap, упаковка байтов в новом порядке через кастинг к байтовому массиву...

Если оттолкнуться от Вашего цикла и использовать битовые операции: Выделяем младший байт источника, копируем в младший байт приёмника.
Сдвигаем источник вправо (теперь второй байт станет младшим),
а приёмник влево (теперь младший байт станет вторым).
Продолжаем, пока исходно младший байт не встанет на старшее место.

 int main()
{
    unsigned int Value = 3496683923;
    unsigned int res = 0;
    std::cout << Value << " " << std::hex << Value << std::endl;
    for (size_t i = 0; i < sizeof(Value); ++i)
    {
        res = (res << 8) | (Value & 0xFF);
        Value >>= 8;
    }
    std::cout << std::dec << res << " " << std::hex << res;
}
3496683923 d06b2993
2468965328 93296bd0

Вариант внутренности цикла, не требующий отказа от const

 {
    res = (res << 8) | ((Value >> 8 * i) & 0xFF);
 }
Answer 2

Например, можно воспользоваться такой функцией:

unsigned int
bswap (unsigned int v)
{
  return (v >> 24) | ((v >> 8) & 0xff00)
    | ((v << 8) & 0xff0000) | (v << 24);
}

Обратите внимание, что тип аргумента -- unsigned.

Впрочем, если вы настаиваете на типе int, как для аргумента, так и для результата, то достаточно привести к unsigned только в одном месте --
return ((unsigned)v >> 24) | ....

Answer 3

Преобразование между little-endian и big-endian предполагает, по определению, смену порядка следования байтов на обратный. Никакого отношения ни к каким "системам счисления" эта тема не имеет вообще.

Сделать это можно массой разнообразных способов... Например, в терминах языка С

uint32_t little_endian = 3496683923;
union { uint32_t v; uint8_t b[4]; } u = { little_endian };
uint8_t t = u.b[0]; u.b[0] = u.b[3]; u.b[3] = t;
        t = u.b[1]; u.b[1] = u.b[2]; u.b[2] = t;
uint32_t big_endian = u.v;
printf("%" PRIu32 "\n", big_endian);
Answer 4

Можно использовать boost.endian:

#include <boost/endian/conversion.hpp>
#include <iostream>
#include <cstdint>
int main()
{
    ::std::int32_t value{};
    ::std::cin >> value;
    ::boost::endian::endian_reverse_inplace(value);
    ::std::cout << value << ::std::endl;
    return 0;
}

online compiler

READ ALSO
Доступ к внутреннем данным элемента TreeView

Доступ к внутреннем данным элемента TreeView

Подскажите чайнику,пожалуйста, как обойти ситуациюВ своем приложении решил создать иерархическую структуру данных

205
Перегрузка оператора присваивания в C++

Перегрузка оператора присваивания в C++

Нужна помощь умных людейНужно: Создать класс СТРОКА, реализующий текстовую строку

163
работа конструктора String(const char*)

работа конструктора String(const char*)

Был такой вопрос: Преобразование char[] в string

135
Как вывести ноль перед числом. С++

Как вывести ноль перед числом. С++

Через std::setfill('0') задаём заполнитель, через std::setw(N) задаём ширину выводимого числаВсё что не занято самим числом будет заполнено символом-заполнителем

196