C++ 11 int8_t 错误 input/output

C++ 11 int8_t buggy input/output

这是我程序中的一段代码。我使用的是 int8_t 数据类型,但我在使用 input/output 时遇到了一些问题。显然,在程序中使用 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应该return0,而不是5。该程序旨在执行 95 / 10 和 return 9 的结果。从理论上讲,这个程序应该可以工作,但显然,即使是除法运算符也有问题。我应该注意,使用 int 而不是 int8_t 会使程序按预期工作。我怀疑在这种情况下,有人只会告诉我使用 int 数据类型并进行处理。但我们是软件工程师!我想知道 int8_t 数据类型是否存在固有缺陷。为什么它不能接受正确的用户输入,还破坏了除法运算符?!任何值得使用的编程语言都必须没有这样的缺陷。而且我认为 C++ 非常流行,最终有人意识到 int8_t 在某种意义上是有缺陷的。那是我需要知道的错综复杂的事情。

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

的别名

其次,当使用 >> 运算符从流中读取 charsignedunsigned)时,它会读取 字符。如果使用别名类型(如 int8_t)并不重要,它仍然是 char 类型并将被读取为字符。

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

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

使用比 int 更小的类型只有当你 read/write 原始二进制数据时才有意义,或者你在一个非常小的嵌入式系统上,每个字节(甚至可能 )计数。

所以反思一些程序员的post,我想补充一下我自己的印象。似乎由于 int8_tchar 的别名,coutcin 自动将变量视为 char,并执行 字符 input/output。我找到了解决这个问题的方法,实际上对变量执行 integer user input/output 。这很简单。我使用 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