0

This is a snipped of code from my program. I am using the int8_t data type, and I'm having some problems with input/output. Apparently, using int8_t in the program requires the -std=c++11 flag to be set for the g++ compiler. I did that, but there are runtime errors. Here's my code:

#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;
}

Here is the output of the program:

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

The $ is the shell prompt. Anyway, it seems that only the first digit is read from the input stream. Even so, the integer division 9 / 10 should return 0, not 5. This program is intended to do 95 / 10 and return a result of 9. Theoretically, this program should work, but apparently, even the division operator is buggy. I should make a note that using int instead of int8_t causes the program to work as intended. I suspect that in this case someone would just tell me to use the int data type and deal with it. But we are software engineers! I would like to know if the int8_t data type is inherently flawed. Why it can't accept proper user input, but also breaks the division operator?! Any programming language worth using must be free of such imperfections. And I think that C++ is popular enough that eventually someone realized that int8_t is flawed in some sense. That is something I need to know the intricacies of.

Galaxy
  • 2,363
  • 2
  • 25
  • 59

2 Answers2

6

First, the smallest type in C++ is char, and on most systems the last couple of decades that's equal to an 8-bit byte. So the type int8_t is usually an alias for signed char.

Second, when reading a char (signed or unsigned) from a stream with the >> operator, it reads a character. It doesn't matter if an alias type (like int8_t) is used, it's still a char type and will be read as a character.

So the result is that you read a single character, and the encoded value of that character is stored in your variable number. With ASCII encoding (the most common character encoding these days) the variable number will store the integer value 57 (ASCII for the character '9') which divided by 10 is equal to the integer 5.

If you want to read a small integer, use int for the type. If you want to store it in a byte (using int8_t) you have to either use temporary int variables, or cast the variable to an int. This casting have to be done for the printing as well (since otherwise the char overload of the << operator will be used) so I recommend using plain int types for any integers by default.

Using smaller types than int is only relevant if you read/write raw binary data, or you're on a very small embedded system where every single byte (or maybe even bit) counts.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
0

So reflecting on Some programmer dude's post, I would like to add my own impressions. It seems that since int8_t is an alias to a char, cout and cin automatically treat the variable as a char, and do character input/output. I figured out a way to get around this, and actually do integer user input/output on the variable. It's simple. I use the C programming language functions printf() and scanf() to do the job. These functions have format specifiers that allow you to treat the variable as being of any data type. Whereas cout and cin automatically interpret the data type, you can do it manually for printf() and scanf(), and that gives you a certain degree of power. Now my code looks like this:

#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;
}

And the actual output looks like this:

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

It's a hack but it works! Well, you learn something new every single day.


Editing this answer, I would like to add some relevant links to related questions for those of you who want to do some more research.

Are int8_t and uint8_t intended to be char types?

Difference between int32, int, int32_t, int8 and int8_t

Galaxy
  • 2,363
  • 2
  • 25
  • 59