14

I'm noticing that cout << hex is giving me strange results, and I cannot find anywhere that answers why. What I am doing is simply assigning some values to both a uint8_t and uint16_t and then attempting to write them to stdout. When I run this:

uint8_t a = 0xab;
uint16_t b = 0x24de;
cout << hex << a << endl;
cout << hex << b << endl;

That I get the result:

$./a.out

24de
$

with no value displayed for the uint8_t. What could be causing this? I didn't think there wouldn't be a cout implementation for one type for not the other.

Odysseas
  • 995
  • 9
  • 21
taronish4
  • 504
  • 3
  • 5
  • 13
  • 3
    BTW `hex` is sticky, once you do it on the first line then it persists until you set `dec`. – M.M May 10 '14 at 00:00
  • 1
    possible duplicate of [uint8\_t can't be printed with cout](http://stackoverflow.com/questions/19562103/uint8-t-cant-be-printed-with-cout) – o11c Jun 16 '15 at 00:04

3 Answers3

24

std::uint8_t is an alias for unsigned char:

typedef unsigned char uint8_t;

So the overload of the inserter that takes a char& is chosen, and the ASCII representation of 0xab is written, which could technically vary by your operating system, as 0xab is in the range of Extended ASCII.

You have to cast it to an integer:

std::cout << std::hex << static_cast<int>(a) << std::endl;
David G
  • 94,763
  • 41
  • 167
  • 253
  • Try to never use a forced cast when an implicit conversion is sufficient. – Ben Voigt May 09 '14 at 23:52
  • @BenVoigt Is an implicit conversion attainable in this expression? – David G May 09 '14 at 23:56
  • 3
    @BenVoigt The trick with `+` is nice, but in my opinion the cast shows clearer intent and is less confusing to anyone looking at the code that might not know the trick. – Retired Ninja May 09 '14 at 23:58
  • @RetiredNinja: Then feel free to use `0u + a`, where it obviously has to produce a result of at least the same size as the larger operand (`unsigned int`). The thing is that if the type of `a` ever changes, the addition operator won't suddenly start doing something stupid, like a cast might. – Ben Voigt May 09 '14 at 23:59
  • @Ben Voigt could you please elaborate: in what kind of situation would a cast do something stupid ? I can't figure out. (I would also do a cast here and I'd like to understand why this could possibly be wrong) – kebs May 10 '14 at 20:02
  • 1
    @kebs: Say you change the variable to `unsigned long long a = 0x123456789abcdefULL;` Or `double a = 1.6;` Now the cast will throw away part of the value, but either unary or binary `+` will print the entire value. – Ben Voigt May 10 '14 at 22:32
  • @Ben Voigt thank you, much clearer now. Indeed, I didn't consider this case where the original type is "larger" than the casted type. – kebs May 11 '14 at 14:37
14

The other answers are correct about the reason. The simplest fix is:

cout << hex << +a << endl;

Demonstration: http://ideone.com/ZHHAHX

It works because operands undergo integer promotion.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
7

uint8_t is an alias for unsigned char. You're essentially printing a character with the value 0xab, which might be an invalid character depending on your encoding.

This would be solvable by casting it to another integer type, converting its value to a string in advance or writing some sort of a wrapper class that implements std::ostream& operator<<(std::ostream&, const ClassName&).