C++ 为什么std::(i)ostream将有符号/无符号字符视为文本而不是整数?
此代码不执行它应该执行的操作:C++ 为什么std::(i)ostream将有符号/无符号字符视为文本而不是整数?,c++,language-lawyer,C++,Language Lawyer,此代码不执行它应该执行的操作: #include <iostream> #include <cstdint> int main() { uint8_t small_integer; std::cin >> small_integer; std::cout << small_integer; } 标准(n3797)中对运算符使用了类似的代码,并将其转换为char,如下所示: 27.7.2.2.3基本istream::ope
#include <iostream>
#include <cstdint>
int main()
{
uint8_t small_integer;
std::cin >> small_integer;
std::cout << small_integer;
}
标准(n3797)中对运算符使用了类似的代码,并将其转换为char
,如下所示:
27.7.2.2.3基本istream::operator>>
模板
基本流和操作员>>(基本流和输入、图表和c);
模板
基本流和运算符>>(基本流和输入,无符号字符和c);
模板
基本流和运算符>>(基本流和输入,签名字符和c);
12效果:其行为类似于中的格式化输入成员(如27.7.2.2.1所述)。构建哨兵对象后,将从中提取字符(如果有),并存储在c中。否则,该函数将调用.setstate(failbit)
27.7.3.6.4字符插入器功能模板
//专门化
模板
基本团队和运营商
这是标准要求的行为吗?如果是,则:
你已经回答了。是的,该标准定义了iostreams应该如何处理有符号和无符号字符
这种违反直觉的语义背后的基本原理是什么
因为signed char
和unsigned char
是字符类型,所以iostreams类总是将它们视为字符
线索在名称中:signed char
是一种有符号字符类型unsigned char
是一种无符号字符类型。其他整数类型的名称中有int
(即使有时是可选的,例如short
和long unsigned
分别与short int
和long unsigned int
相同)
标准不需要说明为什么这是真的,因为它不是一个设计文档或者是C和C++历史的一个基本原理,它是一个规范。
如果希望类型的行为类似于只有8位的整数,则需要创建自己的类型(例如,使用枚举类型或包含值的结构),并定义相关的运算符重载
这是否应该被视为一个缺陷,是否有人建议改变这种语义
不,我不这么认为。它们一直都是字符类型,如果改变它们,会破坏太多的代码。这很烦人。我使用了自己的to_string函数,该函数将(u)int8_t视为整数,而将char视为字符。我为uint8\u t、int8\u t和char添加了单独的专门化,因为我假设这对于不是三种不同类型的人来说是完全有效的。这不是对你问题的回答,而是为了克服这个问题而提出的。@Praetorian,虽然这确实是一个有趣的建议,它解决了一个完全不同的问题。@Matt我假设编译器不能将int8_t
和char
作为参数列表中的类型进行区分。您的to_string
是否真的按照您的意愿工作?如果int8_t
或uint8_t
是char
的typedef,它就不能工作,但如果它们是有符号字符和无符号字符的typedef,它就可以工作。
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);
}
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);
// 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);