此代码没有做它应该做的事情:
#include <iostream>
#include <cstdint>
int main()
{
uint8_t small_integer;
std::cin >> small_integer;
std::cout << small_integer;
}
原因很简单:uint8_t
是unsigned char
的typedef,溪流将此类型视为文字:
Visual C ++ 2015实现
template<class _Traits> inline
basic_istream<char, _Traits>& operator>>(
basic_istream<char, _Traits>& _Istr, unsigned char& _Ch)
{ // extract an unsigned char
return (_Istr >> (char&)_Ch);
}
对char
投射到operator <<
的类似代码。
我的问题:
我应该添加一些解释为什么我认为它违反直觉。
尽管类型名称包含单词char,但signed
或unsigned
部分指定特定的整数语义,并且这些类型通常用作字节大小的整数。甚至标准也通过它们定义int8_t
/ uint8_t
。
UPD:问题是unsigned char
和signed char
的流媒体运营商重载行为。
答案 0 :(得分:3)
标准(n3797)说明如下:
27.7.2.2.3 basic_istream :: operator&gt;&gt;
template<class charT, class traits>
basic_istream<charT,traits>& operator>>(basic_istream<charT,traits>& in, charT& c);
template<class traits>
basic_istream<char,traits>& operator>>(basic_istream<char,traits>& in, unsigned char& c);
template<class traits>
basic_istream<char,traits>& operator>>(basic_istream<char,traits>& in, signed char& c);
12 E ff ects:表现得像in的格式化输入成员(如27.7.2.2.1所述)。构建了一个哨兵对象从中提取一个字符,如果有的话,并存储在c。否则,该函数调用in.setstate(failbit)。
27.7.3.6.4字符插入器功能模板
// specialization
template<class traits>
basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out, char c);
// signed and unsigned
template<class traits>
basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out, signed char c);
template<class traits>
basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out, unsigned char c);
1 E ff ects:表现为out的格式化输出函数(27.7.3.6.1)。构造一个字符序列seq。如果c的类型为char且流的字符类型不是char,则 seq由out.widen(c)组成;否则seq由c 组成。确定seq的填充,如27.7.3.6.1中所述。插入seq。调用os.width(0)。
第一个问题的答案是:是的,标准要求operator >>
和operator <<
对char
,unsigned char
和signed char
的行为完全相同,即他们读/写一个字符,而不是整数。遗憾的是,标准并没有解释原因。我希望有人能够解释2和3。
答案 1 :(得分:1)
- 标准是否需要此行为?如果是的话:
醇>
你已经回答了这个问题。是的,该标准定义了iostream应如何处理有符号和无符号字符。
- 这种违反直觉的语义背后的理由是什么?
醇>
由于signed char
和unsigned char
是字符类型,因此iostreams类始终将它们视为字符。
线索在名称中:signed char
是签名字符类型。 unsigned char
是无符号字符类型。其他整数类型的名称中包含int
(即使它有时是可选的,例如short
和long unsigned
与short int
和long unsigned int
相同分别地)。
标准并不需要说为什么这是真的,因为它不是设计文档或C和C ++历史的基本原理,它是&#39;规范。
如果你想要一个行为类似于只有8位的整数的类型,那么你需要创建自己的类型(例如使用枚举类型或保存值的结构)并定义相关的运算符重载。 / p>
- 如果这被视为缺陷,是否有建议改变这种语义?
醇>
不,我不这么认为。它们一直是字符类型,它会破坏太多代码来改变它。