C++ 为什么int8_t和用户通过cin输入显示出奇怪的结果
一小段代码让我发疯,但希望你能阻止我跳出窗外。看这里:C++ 为什么int8_t和用户通过cin输入显示出奇怪的结果,c++,int,uint8t,C++,Int,Uint8t,一小段代码让我发疯,但希望你能阻止我跳出窗外。看这里: #include <iostream> #include <cstdint> int main() { int8_t i = 65; int8_t j; std::cout << "i = " << i << std::endl; // the 'A' is ok, same as uchar std::cout << "Now t
#include <iostream>
#include <cstdint>
int main()
{
int8_t i = 65;
int8_t j;
std::cout << "i = " << i << std::endl; // the 'A' is ok, same as uchar
std::cout << "Now type in a value for j (use 65 again): " << std::endl;
std::cin >> j;
std::cout << "j = " << j << std::endl;
if (i != j)
std::cout << "What is going on here?????" << std::endl;
else
std::cout << "Everything ok." << std::endl;
return 0;
}
#包括
#包括
int main()
{
int8_t i=65;
int8_t j;
std::coutint8\u t
和uint8\u t
几乎肯定是字符类型()因此,std::cin>>j
将从stdin中读取单个字符,并将其解释为字符,而不是数字。int8\u t
可能与char
相同,这意味着cin>>j
将只读取单个字符('6'
)从输入并将其存储在j
int8\u t
是一种整数类型的typedef,具有所需的特征:纯2的补码表示,无填充位,大小正好为8位
对于大多数(可能是所有)编译器,这意味着它将是有符号字符
的typedef(因为术语有符号整数类型的定义有一个怪癖,它不能是纯字符
的typedef,即使字符
恰好有符号)
>
运算符专门处理字符类型。读取一个字符将读取单个输入字符,而不是表示十进制整数值的字符序列。因此,如果下一个输入字符是'0'
,则读取的值将是字符值'0'
,可能是48
由于typedef
为现有类型而不是新的不同类型创建别名,因此>
运算符无法知道您希望将int8\t
视为整数类型而不是字符类型
问题是,在大多数实现中,没有不是字符类型的8位整数类型
唯一的解决方法是读入int
变量,然后转换为int8\u t
(如果需要,可以进行范围检查)
顺便说一句,int8\u t
是有符号类型;对应的无符号类型是uint8\u t
,其范围为0..255
(还有一个注意事项:如果标准允许CHAR\u BIT>8
,则不会定义int8\u t
或uint8\u t
。)int8\u t
被定义为signed char
的typedef名称。因此操作符>
与int8\u t
类型的对象一起使用时,其行为方式与signed char类型的对象相同
类型不是第一类类型,它们是typedef
别名遵守某些限制,例如,int8\u t
是一种可以存储有符号8位值的类型
在大多数系统上,这意味着它们是typedef
d到char
。因为它们是typedef而不是一级类型,所以您正在调用cin.operator(char)
当您输入“65”时,cin.operator>>(char)
使用“6”,并将其ascii值54放入变量j
要解决此问题,您需要使用不同的类型,最简单的方法可能是使用更大的整数类型并应用约束,然后向下转换:
int8_t fetchInt8(const char* prompt) {
int in = 0;
for ( ; ; ) { // endless loop.
std::cout << prompt << ": ";
std::cin >> in;
if (in >= std::numeric_limits<int8_t>::min()
&& in <= std::numeric_limits<int8_t>::max()) {
std::cout << "You entered: " << in << '\n';
// exit the loop
break;
}
std::cerr << "Error: Invalid number for an int8\n";
}
return static_cast<int8_t>(in);
}
int8\u t fetchInt8(常量字符*提示符){
int in=0;
对于(;){//无止境循环。
std::cout-in;
如果(in>=std::numeric_limits::min()
&&在int8\u t
中可以是任何8位有符号整数类型。char
是完全有效的。我认为,如果\t
类型不允许typedef
到char
(但是无符号
和有符号
char
都可以)。这将阻止它被实现定义。@Keith:谢谢你的回答。我将读取一个int k并将其转换为:j=(int8\t)k、 @JosephMansfield:那没用;cin>>…
将无符号字符
和有符号字符
视为字符类型。@Excalibur:不需要强制转换。只需分配它;转换是隐式完成的。@KeithThompson哦。我认为这也很糟糕。字符
是一种独特的类型,完全是因为它支持sed被视为一种特殊字符类型。它可以是typedef
,用于signed char
或plainchar
@Keith Thompson不,这可能不是因为类型char的行为取决于编译器选项。某些编译器默认将类型char实现为无符号char。将int8_t
定义为plainchar如果明文char
被签名,则code>是完全合法的。如果明文char
的签名依赖于编译器选项,那么int8\t
的定义可以由\if
测试来控制,例如,char\u MAX
。将其定义为有符号的char
当然更容易,但实现却很难不需要合理。@Keith Thompson这是一个错误的语句。char不是无符号整数类型,而uint8\t应定义为无符号整数类型。您是对的。char
是整数类型,它是有符号或无符号的,但它既不是有符号整数类型,也不是无符号整数类型(C和C++标准中定义的术语的一种奇特之处)。可以想象的是,代码>。如果CHAR\u BIT>8
,则根本不会定义int8\u t
。int8\u t
不能与CHAR
的类型相同。它很可能与signed CHAR
的类型相同。