为什么int8_t和用户通过cin输入显示奇怪的结果

Why does int8_t and user input via cin shows strange result

本文关键字:显示 输入 结果 cin int8 用户 为什么      更新时间:2023-10-16

一小段代码让我抓狂,但希望你能阻止我跳出窗外。看这里:

#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代替int8_t,一切正常。我需要它是8位的unsigned integers,不能更大。顺便说一句。对于unsigned char,它的行为-当然-与int8_t相同。

有人能给点提示吗?

int8_t是一个整数类型的typedef,具有以下特征:纯2补码表示,无填充位,长度正好为8位。

对于大多数(也许是所有)编译器,这意味着它将是signed char的typedef(由于术语有符号整数类型的定义中的一个奇怪之处,它不能是普通char的typedef,即使char恰好是有符号的)。

>>运算符对字符类型进行特殊处理。读取字符读取单个输入字符,而不是以十进制表示某个整数值的字符序列。因此,如果下一个输入字符是'0',则读取的值将是字符'0',可能是48。

由于typedef为现有类型创建别名,而不是一个新的不同类型,因此>>运算符无法知道您想将int8_t视为整数类型而不是字符类型。

问题是,在大多数实现中,没有8位整数类型不是字符类型。

唯一的解决方法是读入int变量,然后转换为int8_t(如果需要,可以进行范围检查)。

顺便说一下,int8_t是一个有符号的类型;对应的unsigned类型为uint8_t,取值范围为0 ~ 255。

(还有一点需要注意:如果CHAR_BIT > 8是标准允许的,那么int8_tuint8_t都不会被定义。)

int8_tuint8_t几乎肯定是字符类型(int8_t和uint8_t打算表现得像字符吗?)所以std::cin >> j将从stdin读取单个字符并将其解释为字符,而不是数字。

int8_t可能与char相同,这意味着cin >> j将简单地从输入中读取单个字符('6')并将其存储在j中。

int8_t被定义为signed char的typedef名称。因此,operator >>用于类型为int8_t的对象的行为与用于类型为signed char的对象的行为相同

_t类型不是第一类类型,它们是typedef的别名,遵守一定的约束,例如int8_t是一种可以存储有符号的8位值的类型。

在大多数系统上,这意味着它们是typedef d到char。因为它们是类型定义而不是一等类型,所以您调用的是cin.operator<<(char)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 int8n";
    }
    return static_cast<int8_t>(in);
}

注意,int8_t是有符号的,这意味着它存储-128到+127。如果你只想要正数,使用uint8_t类型。