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

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

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

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

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

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

【问题讨论】:

标签: c++ boost endianness


【解决方案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】:

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

    1. 机器表示遵循 IEEE 754
    2. float/double 的字节序与整数的字节序匹配
    3. 在 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 中定义的。
    猜你喜欢
    • 2022-06-10
    • 2019-06-30
    • 2011-02-09
    • 1970-01-01
    • 2022-12-12
    • 2020-12-01
    • 2018-05-15
    • 1970-01-01
    • 2012-10-09
    相关资源
    最近更新 更多