【问题标题】:C++ 11 int8_t buggy input/outputC++ 11 int8_t 错误输入/输出
【发布时间】:2018-06-06 22:24:42
【问题描述】:

这是我程序中的一段代码。我正在使用int8_t 数据类型,我在输入/输出方面遇到了一些问题。显然,在程序中使用int8_t 需要为g++ 编译器设置-std=c++11 标志。我这样做了,但是存在运行时错误。这是我的代码:

#include <iostream>
#include <cstdint>
using std::cout;
using std::cin;
using std::endl;
int main() {
  int8_t number;

  cout << "Enter a number [1-100]: ";
  cin >> number;
  cout << "You entered: " << number << endl;
  cout << number << " / 10 = " << (number / 10) << endl;

  return 0;
}

这是程序的输出:

 $ ./a.out
Enter a number [1-100]: 95
You entered: 9
9 / 10 = 5

$ 是 shell 提示符。无论如何,似乎只有第一个数字是从输入流中读取的。尽管如此,整数除法9 / 10 应该返回0,而不是5。该程序旨在执行95 / 10 并返回9 的结果。理论上,这个程序应该可以工作,但显然,即使是除法运算符也是有问题的。我应该注意使用int 而不是int8_t 会导致程序按预期工作。我怀疑在这种情况下,有人会告诉我使用 int 数据类型并处理它。但我们是软件工程师!我想知道int8_t 数据类型是否存在固有缺陷。为什么它不能接受正确的用户输入,而且还破坏了除法运算符?!任何值得使用的编程语言都必须没有这样的缺陷。而且我认为 C++ 足够流行,以至于最终有人意识到int8_t 在某种意义上是有缺陷的。这是我需要知道的复杂性。

【问题讨论】:

    标签: c++11 input printf iostream cstdint


    【解决方案1】:

    首先,C++ 中最小的类型是char,在大多数系统上,过去几十年它等于一个 8 位字节。所以int8_t 类型通常是signed char 的别名。

    其次,当使用&gt;&gt; 运算符从流中读取charsignedunsigned)时,它会读取一个字符。是否使用别名类型(如int8_t)无关紧要,它仍然是char 类型并且将被读取为字符。

    所以结果是您读取了一个字符,并且该字符的编码值存储在您的变量number 中。对于ASCII encoding(当今最常见的字符编码),变量number 将存储整数值57(字符'9' 的ASCII)除以10 等于整数5

    如果要读取小整数,请使用int 作为类型。如果要将其存储在一个字节中(使用int8_t),则必须使用临时的int 变量,或者将变量转换为int。这种转换也必须用于打印(因为否则将使用 &lt;&lt; 运算符的 char 重载)所以我建议默认情况下对任何整数使用普通的 int 类型。

    使用比int 更小的类型只有在你读/写原始二进制数据时才有意义,或者你在一个非常小的嵌入式系统上,每个字节(甚至可能是)都很重要.

    【讨论】:

      【解决方案2】:

      所以回顾一些程序员老兄的帖子,我想添加我自己的印象。似乎由于int8_tchar 的别名,coutcin 自动将变量视为char,并执行字符 输入/输出。我想出了一种方法来解决这个问题,并实际上对变量进行 integer 用户输入/输出。这很简单。我使用 C 编程语言函数 printf()scanf() 来完成这项工作。这些函数具有格式说明符,允许您将变量视为任何数据类型。而coutcin 会自动解释数据类型,而您可以手动为printf()scanf() 进行解释,这会给您一定程度的权力。现在我的代码如下所示:

      #include <iostream>
      #include <cstdint>
      #include <cstdio>  // you need this for printf() and scanf()
      using std::cout;
      using std::cin;
      using std::endl;
      int main() {
        int8_t number;
      
        cout << "Enter a number [1-100]: ";
        // %hhd allows you to treat int8_t as an integer data type, instead of
        // a character
        scanf("%hhd", &number);
        printf("You entered: %hhd\n", number);
        printf("%hhd / 10 = %hhd\n", number, (number / 10));
      
        return 0;
      }
      

      实际的输出是这样的:

      $ ./a.out
      Enter a number [1-100]: 95
      You entered: 95
      95 / 10 = 9
      

      这是一个 hack,但它有效!好吧,你每天都会学到新东西。


      编辑这个答案,我想为那些想要做更多研究的人添加一些相关问题的相关链接。

      Are int8_t and uint8_t intended to be char types?

      Difference between int32, int, int32_t, int8 and int8_t

      【讨论】:

        猜你喜欢
        • 2013-05-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-17
        相关资源
        最近更新 更多