c++ 在写入Buffer类时,我需要考虑主机的字节序吗?

w6mmgewl  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(106)

我正在写一个Buffer类,它只是在C++中保存字节。它有各种类型的常用读写方法; 16位,32位和64位整数,浮点数和双精度数。我主要用它来进行内存加载/处理和文件I/O,可能以后也会用到一些网络用途。
与完全依赖于主机的字节序不同,该类有一个内置的字节序开关,因此所有的读和写方法都将以所需的顺序将给定值的底层字节读/写到它们的目的地。
我的问题是,我是否应该考虑运行这个程序的机器的字节顺序,同时也观察缓冲区的所选字节顺序模式?
范例:

void Buffer::WriteInt32(int _int)
{
    bvec bytes;
    for (int i = 0; i < SIZE_INT32; i++)
    {
        bytes.push_back
        (
            _int >> (m_Endianness == Endian::BIG ? ((SIZE_INT32 * 8) - ((i + 1) * 8)) : i * 8)
        );
    }

    m_Bytes.insert(std::end(m_Bytes), std::begin(bytes), std::end(bytes));
    m_Length += SIZE_INT32;
}

字符串
这个例子的方法是有效的,并根据用户的喜好以大或小的字节顺序写入。然而,我有一个潜在的怀疑,我应该检查运行此代码的机器的字节顺序,如果系统的字节顺序和缓冲区的设置匹配,我应该直接写入字节而不改变.这是我应该做的吗?由于我实际上没有在另一台机器上进行测试的选项,所以我对这种情况可能会如何发展感到困惑。
同样,对于阅读:

bool Buffer::ReadInt32(int& dest, bool useOffset, size_t offset)
{
    int val = 0;
    size_t index = useOffset ? offset : m_ReadOffset;
    if (ReadableRemaining(index) < SIZE_INT32)
        return false;

    for (auto i = 0; i < SIZE_INT32; i++)
    {
        val <<= 8;
        val |= m_Bytes[m_Endianness == Endian::BIG ? F_VAL(index, i) : R_VAL(index, i, SIZE_INT32)];
    }

    dest = val;

    m_LastReadSize = SIZE_INT32;
    if (!useOffset)
        AdvanceReadOffset();

    return true;
}


这段代码将从4个字节中检索到的值存储到给定的整数目标中;观察字节的顺序基于缓冲区的字节顺序设置。同样,所有工作都很好,但是运行这段代码的机器是否可以反转val的输出?我是否需要在这里添加代码以根据主机交换内容?

ugmeyewa

ugmeyewa1#

我想了想,也回答了自己的问题,只是当时有一种模糊的感觉,让我看不清楚:)
鉴于:
1.大、小端机器根据它们指定的布局将它们的值存储在内存中;
1.我的缓冲区类只按照给定的顺序存储原始字节,供以后在内存和其他地方使用;
1.该类的用户可以单独选择写入缓冲区/从缓冲区读取的每个值的字节序,而不考虑机器的字节序;

显然,在确定每个操作的给定字节范围是否需要反转顺序之前,我需要观察机器的字节顺序。如果机器顺序与所需的操作顺序匹配,则不进行反转;否则,进行反转。

我也考虑了你的一些建议:

  • 切换到使用std::int32_tint64_t等,以避免意外。
  • 我已经用自己硬编码的2/4/8字节大小在读写过程中检查了各种类型的大小,所以切换到固定宽度类型更有意义。
  • 这个项目现在检查IEEE-754浮点一致性的实现,如果没有它,* 将无法编译**。这是一个我很乐意接受的规则。至于复制值的准确性,不同的代码将以最合适的方式处理这个问题;需要确定性的东西很可能不会依赖于基本的float -> bytes -> different machine -> float转换。
  • 项目特定的文件格式已经被设计为小端优先,但也感谢您的建议。

相关问题