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

std::cout deal with uint8_t as a character

本文关键字:处理 字符 cout uint8 Std      更新时间:2023-10-16

如果我运行这段代码:

std::cout << static_cast<uint8_t>(65);

输出:

在ASCII中相当于数字65。这是因为uint8_t被简单地定义为:

typedef unsigned char uint8_t;
  • 这种行为是标准吗?

  • 应该是一个更好的方式来定义uint8_t,保证被处理为一个数字而不是一个字符?

我不能理解的逻辑,如果我想打印一个uint8_t变量的值,它将被打印为一个字符。

注:我用的是MSVS 2013

这个行为是标准的吗

行为是标准的,如果uint8_tunsigned char的类型定义,那么它将始终打印一个字符,因为std::ostreamunsigned char有过载,并将变量的内容作为字符打印出来。

应该是一个更好的方式来定义uint8_t,保证被处理为一个数字而不是一个字符?

为了做到这一点,c++委员会必须引入一个新的基本类型。目前,sizeof()等于1的类型只有charsigned charunsigned char。他们可能会使用bool,但bool不一定要有1的大小,然后你仍然在同一条船上,因为

int main()
{
    bool foo = 42;
    std::cout << foo << 'n';
}

将打印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;
}

发布答案,因为评论中有一些错误信息。

uint8_t可以是charunsigned char的类型定义,也可以不是。它也可以是扩展的整数类型(因此,不是字符类型)。

除了标准(shortintlong等)所要求的最小整数类型之外,编译器还可以提供其他整数类型。例如,一些编译器提供128位整数类型。

这也不会"与C冲突",因为C和c++都允许扩展整数类型。

所以,你的代码必须允许两种可能性。注释中建议使用一元+是可行的。

我个人认为如果标准要求uint8_t 不是是一个字符类型会更有意义,因为你注意到的行为是不直观的。

这是间接的标准行为,因为ostreamunsigned char有重载,而unsigned char是系统中相同类型uint8_t的类型定义。

§27.7.3.1 [output.streams。上ostream]给:

template<class traits>
basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>&, unsigned char);
但是,我在标准中找不到任何地方明确声明uint8_tunsigned char 具有相同。只是在几乎所有的实现中,它们都占用1字节是合理的。
 std::cout << std::boolalpha << std::is_same<uint8_t, unsigned char>::value << std::endl; // prints true

要使值作为整数打印,您需要一个不是unsigned char(或其他字符重载之一)的类型。可能简单地强制转换为uint16_t就足够了,因为标准没有列出它的重载:

uint8_t a = 65;
std::cout << static_cast<uint16_t>(a) << std::endl; // prints 65
演示