有效地在 little-endian 和 big-endian 浮点数之间转换

Posted

技术标签:

【中文标题】有效地在 little-endian 和 big-endian 浮点数之间转换【英文标题】:Convert between little-endian and big-endian floats effectively 【发布时间】:2016-12-19 10:36:38 【问题描述】:

我有一个工作软件,目前在little-endian 架构上运行。我也想让它在big-endian 模式下运行。我想将little-endian 数据写入文件,无论底层系统的字节序如何。

为了实现这一点,我决定使用 boost endian 库。它可以有效地转换整数。但它不能处理浮点数(和双精度数)。

它在documentation 中声明,“Boost 1.59.0 将支持浮点类型”。但是1.62 仍然不支持它们。

我可以假设,浮点数是有效的 IEEE 754 浮点数(或双精度数)。但是它们的字节顺序可能会根据底层系统而有所不同。据我所知,不建议在浮点数上使用 htonlntohl 函数。那怎么可能呢?是否有任何仅包含标头的库,它也可以处理浮点数?我找不到任何东西。

我可以将浮点数转换为字符串,然后将其写入文件,我想避免这种方法,原因有很多(性能、磁盘空间、...)

【问题讨论】:

不需要任何库,它非常直接。看看那里:***.com/questions/2782725/… 【参考方案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

或者当你使用指针时,立即反转,使用:

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

祝你好运。

【讨论】:

浮动1 没有过载。但仍然需要强制反转字节序【参考方案3】:

在序列化浮点/双精度值时,我做了以下三个假设:

    机器表示遵循 IEEE 754 float/double 的字节序与整数的字节序匹配 在 double&/int64_t& 或 float&/int32_t& 之间进行 reinterpret_cast-ing 的行为是明确定义的(例如,转换的行为就像类型相似一样)。

标准不保证这些假设。在这些假设下,以下代码将确保双精度以 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));

【讨论】:

我可能应该补充一点,boost::endian::native_to_little_inplace 是在 boost/endian/conversion.hpp 中定义的。

以上是关于有效地在 little-endian 和 big-endian 浮点数之间转换的主要内容,如果未能解决你的问题,请参考以下文章

关于big-endian和little-endian

小端格式和大端格式(Little-Endian&Big-Endian)

小端格式和大端格式(Little-Endian&Big-Endian)

小端格式和大端格式(Little-Endian&Big-Endian)

c_cpp Ledger SDK解包Big / Little-Endian 8字节Uint64

BigInteger简析