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

时间:2016-08-25 12:47:16

标签: c++ c++11 language-lawyer cout fixed-size-types

如果我运行此代码:

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

将输出:

  

A

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

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

  • 不应该更好地定义uint8_t来保证作为数字处理而不是字符?

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

P.S。我正在使用MSVS 2013。

3 个答案:

答案 0 :(得分:3)

  

此行为是否为标准

行为是标准的,如果uint8_tunsigned char的typedef,那么它将始终打印一个字符,因为std::ostream具有unsigned char的重载并打印出来变量的内容作为字符。

  

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

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

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

将打印1,而不是42,因为任何非零都为真,而真打印为1但默认为。

我并不是说不能这样做但是对于可以用cast or a function

处理的事情来说,这是很多工作。

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;
}

答案 1 :(得分:3)

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

§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

Demo

答案 2 :(得分:3)

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

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

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

这不会与C&#34;冲突。或者,因为C和C ++都允许扩展的整数类型。

因此,您的代码必须考虑到这两种可能性。使用一元+的评论中的建议可行。

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