Are int8_t and uint8_t intended to be char types?

c++, c++11, iostream, language-lawyer, standard-library

Solution

From § 18.4.1 [cstdint.syn] of the C++0x FDIS (N3290), `int8_t` is an optional typedef that is specified as follows:

namespace std {
  typedef signed integer type int8_t;  // optional
  //...
} // namespace std

§ 3.9.1 [basic.fundamental] states:

There are five standard signed integer types: “`signed char`”, “`short int`”, “`int`”, “`long int`”, and “`long long int`”. In this list, each type provides at least as much storage as those preceding it in the list. There may also be implementation-defined extended signed integer types. The standard and extended signed integer types are collectively called signed integer types.

...

Types `bool`, `char`, `char16_t`, `char32_t`, `wchar_t`, and the signed and unsigned integer types are collectively called integral types. A synonym for integral type is integer type.

§ 3.9.1 also states:

In any particular implementation, a plain `char` object can take on either the same values as a `signed char` or an `unsigned char`; which one is implementation-defined.

It is tempting to conclude that `int8_t` may be a typedef of `char` provided `char` objects take on signed values; however, this is not the case as `char` is not among the list of signed integer types (standard and possibly extended signed integer types). See also Stephan T. Lavavej's comments on `std::make_unsigned` and `std::make_signed`.

Therefore, either `int8_t` is a typedef of `signed char` or it is an extended signed integer type whose objects occupy exactly 8 bits of storage.

To answer your question, though, you should not make assumptions. Because functions of both forms `x.operator<<(y)` and `operator<<(x,y)` have been defined, § 13.5.3 [over.binary] says that we refer to § 13.3.1.2 [over.match.oper] to determine the interpretation of `std::cout << i`. § 13.3.1.2 in turn says that the implementation selects from the set of candidate functions according to § 13.3.2 and § 13.3.3. We then look to § 13.3.3.2 [over.ics.rank] to determine that:

- The `template<class traits> basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>&, signed char)` template would be called if `int8_t` is an Exact Match for `signed char` (i.e. a typedef of `signed char`).

- Otherwise, the `int8_t` would be promoted to `int` and the `basic_ostream<charT,traits>& operator<<(int n)` member function would be called.

In the case of `std::cout << u` for `u` a `uint8_t` object:

- The `template<class traits> basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>&, unsigned char)` template would be called if `uint8_t` is an Exact Match for `unsigned char`.

- Otherwise, since `int` can represent all `uint8_t` values, the `uint8_t` would be promoted to `int` and the `basic_ostream<charT,traits>& operator<<(int n)` member function would be called.

If you always want to print a character, the safest and most clear option is:

std::cout << static_cast<signed char>(i);

And if you always want to print a number:

std::cout << static_cast<int>(i);

Problem

Given this C++11 program, should I expect to see a number or a letter? Or not make expectations? ``` #include <cstdint> #include <iostream> int main() { int8_t i = 65; std::cout << i; } ``` Does the standard specify whether this type can or will be a character type?

Original source

Related problems