如果我运行此代码:
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。
答案 0 :(得分:3)
此行为是否为标准
行为是标准的,如果uint8_t
是unsigned char
的typedef,那么它将始终打印一个字符,因为std::ostream
具有unsigned char
的重载并打印出来变量的内容作为字符。
不应该是一个更好的方法来定义
uint8_t
保证作为数字处理而不是字符?
为了做到这一点,C ++委员会将不得不引入一种新的基本类型。目前,sizeof()
等于1的唯一类型是char
,signed char
和unsigned 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)
这是间接的标准行为,因为ostream
有unsigned 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_t
和unsigned 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
答案 2 :(得分:3)
发表回答,因为评论中有一些错误信息。
uint8_t
可能是也可能不是char
或unsigned char
的typedef。它也可以是扩展的整数类型(因此,不是字符类型)。
除了标准所要求的最小集合(short
,int
,long
等)之外,编译器还可以提供其他整数类型。例如,某些编译器提供128位整数类型。
这不会与C&#34;冲突。或者,因为C和C ++都允许扩展的整数类型。
因此,您的代码必须考虑到这两种可能性。使用一元+
的评论中的建议可行。
我个人认为如果标准要求uint8_t
不是一个字符类型会更有意义,因为你注意到的行为是不直观的。