How do I use an uint8_t with I/O streams while avoiding the char behavior?

Viewed 743

Consider this simple C++ program:

#include <cstdint>
#include <iostream>

int main() {
    uint8_t var;
    std::cin >> var;
    std::cout << "var = " << var << '\n';
    if (var == 1) {
        std::cout << "var is 1\n";
    } else {
        std::cout << "var is not 1\n";
    }
}

Running it shows some surprising behavior. When the input is 1, the output is

var = 1
var is not 1

which is clearly absurd! After quite a few varied tests, I realized what is happening—it's reading and writing a char! Still, it's not the behavior I want—I used uint8_t because I want the integer behavior. How can I make uint8_t behave like the other integer types when doing stream I/O? Alternatively, what one-byte type should I use instead?

2 Answers

You need to cast to int:

std::cout << "var = " << static_cast<int>(var) << '\n';

or shorter (C-style):

std::cout << "var = " << (int)var << '\n';   //or:
std::cout << "var = " << int(var) << '\n';   //constructor-like

or even shorter (promoting to int with an arithmetic operator):

std::cout << "var = " << +var << '\n';

How can I make uint8_t behave like the other integer types when doing stream I/O?

You can't. Apparently you can.

If std::uint8_t is an alias of unsigned char, as it usually (maybe always) is, then it is a character type, and the standard streams treat it as a character type.

You can convert it to a non-character integer type before inserting to a stream:

 std::cout << "var = " << static_cast<unsigned>(var) << '\n';

Or with an intermediary variable:

unsigned temp = var;
std::cout << "var = " << temp << '\n';

Stream extraction works only with the intermediary variable approach:

unsigned temp;
std::cin >> temp;
var = temp;

On a related note, if you wish to output the address of a variable, then std::cout << &var; won't work, because it will be treated as a null terminated string... which it isn't and thus results in undefined behaviour. To achieve that, you can use std::cout << static_cast<void*>(&var);.

Related