4

我希望了解有关 uint8_t 与 char、可移植性、位操作、最佳实践、事态等方面的情况。您知道有关该主题的好读物吗?

我想做字节IO。但当然 char 的定义比 uint8_t 更复杂、更微妙;我认为这是引入 stdint 标头的原因之一。

但是,我在多次使用 uint8_t 时遇到了问题。几个月前,一次,因为 iostreams 没有为 uint8_t 定义。是不是有一个 C++ 库在做真正定义良好的字节 IO,即读写 uint8_t?如果没有,我认为没有需求。为什么?

我最近的头痛源于此代码无法编译:

uint8_t read(decltype(cin) & s)
{
    char c;
    s.get(c);
    return reinterpret_cast<uint8_t>(c);
}

error: invalid cast from type 'char' to type 'uint8_t {aka unsigned char}'

为什么会出错?如何使这项工作?

4

2 回答 2

2

通用的、便携的、往返正确的方法是:

  1. 在您的 API 中要求所有字节值最多可以用 8 位表示,
  2. 对 I/O使用 和 的布局兼容性charsigned char以及unsigned char
  3. 根据需要转换unsigned charuint8_t

例如:

bool read_one_byte(std::istream & is, uint8_t * out)
{
    unsigned char x;    // a "byte" on your system 
    if (is.get(reinterpret_cast<char *>(&x)))
    {
        *out = x;
        return true;
    }
    return false;
}

bool write_one_byte(std::ostream & os, uint8_t val)
{
    unsigned char x = val;
    return os.write(reinterpret_cast<char const *>(&x), 1);
}

一些解释:规则 1 保证值可以在不丢失信息uint8_t的情况下往返转换。unsigned char规则 2 意味着我们可以对unsigned char变量使用 iostream I/O 操作,即使它们以chars 表示。

我们也可以使用is.read(reinterpret_cast<char *>(&x), 1)而不是is.get() 对称。(read一般情况下,对于大于 1 的流计数,也需要使用gcount()on error,但这不适用于此处。)

与往常一样,您绝不能忽略 I/O 操作的返回值。这样做总是程序中的错误。

于 2014-10-05T12:57:46.680 回答
0

几个月前,一次,因为 iostreams 没有为 uint8_t 定义。

uint8_t几乎只是unsigned char. 事实上,我怀疑你能找到一台没有的机器。

uint8_t read(decltype(cin) & s)
{
    char c;
    s.get(c);
    return reinterpret_cast<uint8_t>(c);
}

使用decltype(cin)而不是std::istream根本没有任何优势,它只是一个潜在的混乱来源。- 语句中的return强制转换是不必要的;将 a隐式转换为作品charunsigned char

几个月前,一次,因为 iostreams 没有为 uint8_t 定义。

他们是。不是为了uint8_t它自己,而是为了它实际代表的类型。operator>> 为unsigned char. 此代码有效:

uint8_t read(istream& s)
{
    return s.get();
}

因为unsigned charandchar可以互相别名,所以你也可以只是指向一个字符串的reinterpret_cast任何指针,然后使用它。charunsigned char*

如果您想要最便携的方式,请查看 Kerreks 的答案。

于 2014-10-05T12:52:05.747 回答