0

The Following code does not work as expected:

#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
#include <cstdint>

int main()
{
    std::stringstream ss;
    ss << std::setfill('0') << std::hex << std::setw(2) << std::int8_t(-1);
    std::cout << ss.str() << std::endl;
}

What I want is to convert a signed char to a fixed length hex representation. The output is always 0�.

Converting to unsigned int also print unexpected output:

ss << std::setfill('0') << std::hex << std::setw(2) << (unsigned int)std::int8_t(-1);

This will print ffffffff which is correct but I told the stream to set the width to 2. Is there any way to work around this?

Gustavo
  • 919
  • 11
  • 34
  • 1
    If you want the hex value of a `char` or `unsigned char`, please, convert it to `int` or `unsigned`. The overloaded stream output operators for `char` and `unsigned char` are intended to write characters (but not their integral values). To fix your latter issue, a two step conversion will help: `(unsigned)(unsigned char)std::int8_t(-1)`. Otherwise, you get a sign extension - hence the 8 `f`s (representing the bit pattern of a 32 bit -1). – Scheff's Cat Jul 16 '20 at 12:13

2 Answers2

1

You have to cast the -1 to uint8_t to get 255, casted to unsigned int will stay at 255, which then gets printed as ff:

ss << std::setfill('0') << std::hex << std::setw(2) << (unsigned int)std::uint8_t(-1);

When you cast it to int8_t, it will stay at -1, casted to unsigned int will give you 4294967295, which then will be printed as ffffffff.

mch
  • 9,424
  • 2
  • 28
  • 42
0

You need to cast to unsigned char first, to get the value in range 0-255:

ss << std::setfill('0') << std::hex << std::setw(2) << (int)std::uint8_t(-1);

Then it is cast to any integral type bigger than char (here int) to make it print as number and not character.

Yksisarvinen
  • 18,008
  • 2
  • 24
  • 52