简体   繁体   English

有效地在小端和大端浮点数之间转换

[英]Convert between little-endian and big-endian floats effectively

I have a working software, which currently runs on a little-endian architecture.我有一个可以运行的软件,它目前在little-endian架构上运行。 I would like to make it run in big-endian mode too.我也想让它以big-endian模式运行。 I would like to write little-endian data into files, regardless of the endianness of the underlying system.无论底层系统的字节序如何,我都想将little-endian数据写入文件。

To achieve this, I decided to use the boost endian library.为了实现这一点,我决定使用 boost endian 库。 It can convert integers efficiently.它可以有效地转换整数。 But it cannot handle floats (and doubles).但它不能处理浮动(和双打)。

It states in the documentation , that " Floating point types will be supported in the Boost 1.59.0 ".它在文档中指出,“ Boost 1.59.0 将支持浮点类型”。 But they are still not supported in 1.62 .但是它们在1.62中仍然不受支持。

I can assume, that the floats are valid IEEE 754 floats (or doubles).我可以假设,浮点数是有效的IEEE 754浮点数(或双精度数)。 But their endianness may vary according to the underlying system.但是它们的字节顺序可能会因底层系统而异。 As far as I know, using the htonl and ntohl functions on floats is not recommended.据我所知,不建议在浮动上使用htonlntohl函数。 How is it possible then?那怎么可能呢? Is there any header-only library, which can handle floats too?是否有任何头文件库,它也可以处理浮点数? I was not able to find any.我找不到任何东西。

I could convert the floats to string, and write that into a file, I would like to avoid that method, for many reasons ( performance, disk-space, ... )我可以将浮点数转换为字符串,并将其写入文件,出于多种原因(性能、磁盘空间……),我想避免使用该方法

Here:这里:

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

No need for anything fancy.不需要任何花哨的东西。

Unheilig: you are correct, but 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
}

or when u are using pointers, to immediate reversing, use:或者当您使用指针时,要立即反转,请使用:

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

and use it, instead of manually (or maybe error-prone) reversing it's content并使用它,而不是手动(或者可能容易出错)反转它的内容

example:例子:

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

Good luck.祝你好运。

When serializing float/double values, I make the following three assumptions:在序列化 float/double 值时,我做出以下三个假设:

  1. The machine representation follows IEEE 754机器表示遵循 IEEE 754
  2. The endianess of float/double matches the endianess of integers float/double 的字节序匹配整数的字节序
  3. The behavior of reinterpret_cast-ing between double&/int64_t& or float&/int32_t& is well-defined (Eg, the cast behaves as if the types are similar).在 double&/int64_t& 或 float&/int32_t& 之间 reinterpret_cast-ing 的行为是明确定义的(例如,强制转换的行为就像类型相似)。

None of these assumptions is guaranteed by the standard.这些假设都不是由标准保证的。 Under these assumptions, the following code will ensure doubles are written in little-endian:在这些假设下,以下代码将确保以小端顺序编写双打:

ostream out;
double someVal;
...
static_assert(sizeof(someVal) == sizeof(int64_t),
    "Endian conversion requires 8-byte doubles");
native_to_little_inplace(reinterpret_cast<int64_t&>(someVal));
out.write(reinterpret_cast<char*>(&someVal), sizeof(someVal));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM