4

Given the following code.

#include <cstdint>
#include <iostream>
#include <limits>

int main()
{
    int8_t x = 5;
    std::cout << x << '\n';

    int y = 5;
    std::cout << y;

    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    std::cin.get();

    return 0;
}

My output is a three-leaf clover and 5. If fixed-width integers are integers, why are they outputting their number's ASCII character symbol?

Edit: just found out this behavior only happens for 8-bit fixed-width integers? Is this compiler behavior?

Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
Wandering Fool
  • 2,170
  • 3
  • 18
  • 48

2 Answers2

12

Well, they are integers in the sense that you can do 8 bit integer arithmetic with them.

But apparently on your system, int8_t is implemented as a typedef to signed char. This is completely legal since signed chars are also integers, but gives unexpected results since the operator<< for signed chars prints their character symbol and not their numeric value. Anything else would just be weird if someone tried to print an signed char.

If you want to see the numeric value of your int8_t, just cast to int before printing.

Havenard
  • 27,022
  • 5
  • 36
  • 62
Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
2

The (optional) fixed-width types intN_t, and also various other types like uint_fast16_t, uintmax_t and intptr_t, are aliases for one of the built-in integral types. You don't know what the actual types they're aliasing are, only that they must meet the documented constraints.

In the case of "exactly 8 bits", the constraints don't leave much room, though, and the only integral types that can be 8 bits wide are the char types (recall there are three of them). So int8_t, if it exists, must be an alias for either char or signed char.

Unrelatedly, iostreams defines overloads for operator<< for the all character types which have the effect of writing the value directly to the output rather than formatting the integer as a decimal string (this is so that you can conveniently write std::cout << 'a'), and this overload is also used for int8_t -- overload resolution works on types, not on type names. (It is perhaps regrettable that there is an special ostream overload for signed char; it might have been nicer to only provide the overload for char and treat the other types like ordinary integers.) That's why you see the value printed as a character in your system's encoding.

If you want to print the value formatted as a string, just convert it to one of the wider integral types. For example, you can apply the standard promotions with the unary plus: int8_t x = 5; std::cout << +x;

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • Must they really be aliases for the "built-in" integral types? – MSalters May 25 '15 at 23:37
  • @MSalters: Yes. The relevant wording is in the C standard, from which this library component is imported. The term "signed integer type" is a term of art, defined in "Language/Concepts/Types". – Kerrek SB May 25 '15 at 23:40
  • @Kerrek SB I never heard of using +x to change a char to an integer in the output. I thought it was just a redundant unary operator which explicitly stated a value was positive? – Wandering Fool May 25 '15 at 23:41
  • @WanderingIdiot: The C++ type system is bewilderingly complex. [Default promotions and arithmetic conversions](http://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Core-C-/Stephan-T-Lavavej-Core-C-7-of-n) are not to be taken lightly :-S – Kerrek SB May 25 '15 at 23:44
  • @WanderingIdiot the arithmetic operators all promote any integral type narrower than `int` to `int` before operating. – M.M May 25 '15 at 23:59
  • @MattMcNabb: Or `unsigned int`, depending on the weather. – Kerrek SB May 26 '15 at 08:20
  • @KerrekSB by "narrower" I meant being of fewer (value) bits . Promotion to `unsigned int` only happens if the signed type was the same width but lower rank. – M.M May 26 '15 at 08:22
  • @MattMcNabb: I see, yes. But then your statement was incomplete, since integral types that are not narrower may also be promoted (e.g. `signed char` and `short int` may have the same width as `int`, but are still promoted). – Kerrek SB May 26 '15 at 08:51