Перевод в big-endian, проблемы с данными типа signed

184
03 февраля 2020, 10:00

Прошу помощи со следующим вопросом. Имеется бинарный файл, достаточно большой. Большая часть данных записаны в порядке от старшего байта к младшему. До некоторого момента у меня не возникало проблем, т.к. все данные были строго положительные. К слову использовал я библиотеку endian.h , и я почти уверен, что она стандартная. Приведу пример того, как я это делаю, основанный на моем коде:

string fileName = "NSS.AMAX.NK.D11171.S1811.E1941.B6812425.WI";
ifstream in(fileName.c_str(), ios::binary);
int32_t i4;
in.read((char *)&i4, 4);
cout << "latitude: " << htobe32(i4) << endl;

Примерно таким образом я и парсил файл, но вот незадача, htobe32 работает только с типом unsigned, что меня не устраивает. Т.к. некоторые числа, такие как широта и долгота в моем случае могут быть отрицательными. Так например перевод в big-endian на C# у меня выглядел так:

 if (BitConverter.IsLittleEndian)
 {
 Array.Reverse(item);
 Console.Write(BitConverter.ToInt32(item, 0));
 }

Тут item - это массив байтов byte[]. И работал код с любым типом int. Собственно в случае, когда на C# я получал логичное -542112, то на плюсах несуразное 4294425184. Это запись записана как градусы*(10^4). То есть грубо говоря я получаю -54,2112 градуса. Вот такой же результат мне бы хотелось видеть в С++. Я не очень умный и потому очень прошу подробно объяснить ответ. Спасибо :-)

Answer 1

Может быть кому-нибудь пригодится, оказалось все просто. Ответ нашел на форуме линуксоедов от пользователя arsi 2009г. Ответ был написан для unsigned типа, но переделать метод было проще простого.

int32_t htobe32s(int32_t x)
{
    union {
        int32_t u32;
        int8_t v[4];
    } ret;
    ret.v[0] = (uint8_t)(x >> 24);
    ret.v[1] = (uint8_t)(x >> 16);
    ret.v[2] = (uint8_t)(x >> 8);
    ret.v[3] = (uint8_t)x;
    return ret.u32;
}
Answer 2

Достаточно воспользоваться boost.endian:

#include <boost/endian/arithmetic.hpp>
#include <cstdio>
#include <cstdint>
int main()
{
    ::std::int32_t const native{123456789};
    ::std::int32_t const big_endian{::boost::endian::native_to_big(native)};
    ::std::printf("Native    %08x\nBigEndian %08x\n", native, big_endian);
    return 0;
}
READ ALSO
QMapControl проблема с яндекс картами

QMapControl проблема с яндекс картами

Захотелось отображать яндекс карты в QMapControl, для этого создал yandexMapAdapter

161
Настройка включения библиотек для cxxtest [закрыт]

Настройка включения библиотек для cxxtest [закрыт]

Хотите улучшить этот вопрос? Переформулируйте вопрос, чтобы он соответствовал тематике «Stack Overflow на русском»

183
эхоподавление на с++

эхоподавление на с++

Реализую небольшой проект по воспроизведении аудио данных, в том числе и с микрофонаДля воспроизведения пользуюсь библиотекой soundiolib, библиотека...

166
stack around the variable &ldquo;pd&rdquo; was corrupted

stack around the variable “pd” was corrupted

Программа должна считывать из файла элементы матрицы, но в конце выдаёт ошибку stack around the variable pd was corruptedГде ошибка?

182