8

Consider code like this:

#include <iostream>
#include <sstream>

int main()
{
    std::stringstream ss;
    ss << "a0 b1";

    uint8_t byte;
    ss >> std::hex >> byte;    

    std::cout << std::hex << byte << std::endl;

    return 0;
}

Why does this output a instead of a0 even though a0 fits in uint8_t as hex?

juzzlin
  • 45,029
  • 5
  • 38
  • 50

1 Answers1

12

Because uint8_t is also (probably) unsigned char, for which special rules exist when you perform formatted extraction from a C++ stream.

Unfortunately this is just an alias, not a distinct type.

Basically it's skipping the "lexically convert to a number" step because it thinks you want to pull out a character. The character 'a'.

I think you'll want to read into an unsigned int then downsize if needed.

If you do downsize to a uint8_t, you're also going then to have to promote it back to a larger int (lol) for much the same reason, to trigger serialisation.

(live demo)

To be honest I'd just avoid the small fixed-width types when dealing with streams (unless you're doing unformatted work with read() and write()). It's too easy to forget about this problem.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • Yeah, the code looks really stupid with all those casts :) – juzzlin Jun 04 '19 at 14:45
  • 3
    @Brandon The unary plus operator causes the `uint8_t` operand be promoted to `int`, which becomes type of the expression result. – eerorika Jun 04 '19 at 14:49
  • 1
    @Brandon That's [the cheat's way to perform the mentioned integral promotion](https://stackoverflow.com/a/3903114/560648). – Lightness Races in Orbit Jun 04 '19 at 14:50
  • If I am not mistaken the base type of c++ streams is char not an unsigned char. How would this influence the result? – Bart Jun 04 '19 at 14:50
  • @Bart The base type is irrelevant. IOStreams have special overloads for `char`ry things. Otherwise streaming your `'a'` `'b'` `'c'` etc would not work properly. (Actually it's more like it has special overloads for **non** `char`ry things; that's your `int`, `bool` etc. But you get so used to it that you forget `char`, `unsigned char` etc _don't_ do that.) – Lightness Races in Orbit Jun 04 '19 at 14:51