Преобразование между малыми и средними значениями поплавков эффективно

У меня есть рабочее программное обеспечение, которое в настоящее время работает в архитектуре little-endian. Я хотел бы запустить его в режиме big-endian. Я хотел бы написать little-endian данные в файлы, независимо от того, является ли эта система базовой.

Чтобы достичь этого, я решил использовать библиотеку boost endian. Он может эффективно конвертировать целые числа. Но он не может обрабатывать поплавки (и удваивает).

Он указывает в documentation, что "типы плавающей точки будут поддерживаться в Boost 1.59.0". Но они все еще не поддерживаются в 1.62.

Я могу предположить, что поплавки действительны IEEE 754 поплавки (или удваиваются). Но их сущность может варьироваться в зависимости от базовой системы. Насколько мне известно, использование функций htonl и ntohl в поплавках не рекомендуется. Как это возможно? Есть ли какая-либо библиотека только для заголовка, которая также может обрабатывать поплавки? Я не смог найти.

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

Ответ 1

Здесь:

float f = 1.2f;
auto it = reinterpret_cast<uint8_t*>(&f);
std::reverse(it, it + sizeof(f)); //f is now in the reversed endianness

Ничего не нужно.

Ответ 2

Unheilig: вы правы, но

#include <boost/endian/conversion.hpp>


template <typename T>
inline T endian_cast(const T & t)
{
#ifdef BOOST_LITTLE_ENDIAN
    return boost::endian::endian_reverse(t);
#else
    return t;
#endif
}

или когда u использует указатели, для немедленного реверса используйте:

template <typename T>
inline T endian_cast(T *t)
{
#ifdef BOOST_LITTLE_ENDIAN
    return boost::endian::endian_reverse_inplace(*t);
#else
    return t;
#endif
}

и использовать его вместо ручного (или, возможно, подверженного ошибкам) ​​изменения его содержимого

Пример:

std::uint16_t start_address() const
{
    std::uint16_t address;
    std::memcpy(&address, &data()[1], 2);
    return endian_cast(address);
}
void start_address(std::uint16_t i)
{
    endian_cast(&i);
    std::memcpy(&data()[1], &i, 2);
}

Удачи.