std::cout 将 uint8_t 作为字符处理

Hum*_*awi 5 c++ cout language-lawyer c++11 fixed-size-types

如果我运行此代码:

std::cout << static_cast<uint8_t>(65);
Run Code Online (Sandbox Code Playgroud)

它会输出:

一种

这是数字 65 的 ASCII 等价物。这是因为它uint8_t被简单地定义为:

typedef unsigned char uint8_t;
Run Code Online (Sandbox Code Playgroud)
  • 这种行为是标准吗?

  • 不应该是定义uint8_t保证被处理为数字而不是字符的更好方法吗?

我无法理解如果我想打印uint8_t变量的值,它将被打印为字符的逻辑。

PS 我使用的是 MSVS 2013。

Nat*_*ica 5

这种行为是标准吗

该行为是标准的,因为 ifuint8_t是 typedef of unsigned charthen 它将始终打印一个字符,因为std::ostream具有重载 forunsigned char并将变量的内容打印为字符。

不应该是更好的方法来定义uint8_t保证被处理为数字而不是字符吗?

为了做到这一点,C++ 委员会必须引入一种新的基本类型。sizeof()目前,a等于 1 的唯一类型是charsigned charunsigned char。他们可能可以使用 a,boolbool不必使用 1 的大小,然后您仍然在同一条船上,因为

int main()
{
    bool foo = 42;
    std::cout << foo << '\n';
}
Run Code Online (Sandbox Code Playgroud)

将打印1,而不是42因为任何非零都是 true 并且 true 被打印为1默认值。

我并不是说它不能完成,但对于可以通过强制转换或函数处理的事情来说,这是一项大量的工作


C++17 引入了std::byte定义为enum class byte : unsigned char {};. 所以它将是一个字节宽,但它不是字符类型。不幸的是,既然它是一个enum class它就有它自己的局限性。已为其定义了按位运算符,但没有内置的流运算符,因此您需要定义自己的运算符来输入和输出它。这意味着您仍在转换它,但至少不会与 的内置运算符发生冲突unsigned char。这给了你类似的东西

std::ostream& operator <<(std::ostream& os, std::byte b)
{
    return os << std::to_integer<unsigned int>(b);
}

std::istream& operator <<(std::istream& is, std::byte& b)
{
    unsigned int temp;
    is >> temp;
    b = std::byte{b};
    return is;
}

int main()
{
    std::byte foo{10};
    std::cout << foo;
}
Run Code Online (Sandbox Code Playgroud)