• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 316
  • Last Modified:

convert to hexadecimal

I am trying to understand how the runtime converts this to hex

	std::stringstream s;
        s << std::hex;    
	int i = 0;
        s << std::setw(2) << std::setfill('0') << (unsigned int)(unsigned char)a[i];      // WORKS
        s << std::setw(2) << std::setfill('0') << (unsigned int)a[i];     // DOES NOT WORK

Open in new window

1.  Why do we need this line
      s << std::hex;    

2) Why does it not work without (unsigned char)
2 Solutions
käµfm³d 👽Commented:
It's a stream manipulator. It coerces the stream to read its data as hexadecimal (where as the default is decimal). You could certainly read the data as a string first, and then do the conversion to hexadecimal value, but this would take a bit more code.

As to why it does not work without (unsigned char), what is the type of your a array?
perlperlAuthor Commented:
The array was void* and passed to this function as const char*
You could use a 'unsigned int*' cast since it is an array, e.g.

        s << std::setw(2) << std::setfill('0') << ((unsigned int*)a)[i];

Open in new window

Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

perlperlAuthor Commented:
Thanks jkr. that works too
but I am trying to understand my solution as why
this works   (unsigned int)(unsigned char)
and why this not    (unsigned int)a
>>but I am trying to understand my solution as why
>>this works   (unsigned int)(unsigned char)

This only works because you are printing 2-digit hexadecimal expressions that consist of one byte only. That will fail for values that consist of more than one byte..

Basically, you are casting 'void a[x]' to 'unsigned char' first. OK, that's fine. The next cast makes it clear to the stringstream that you want an unsigned int to be printed, so the single byte taken from 'a[ix]' (as a char) is taken and converted.
2) Why does it not work without (unsigned char)
there are two reasons:
- a void pointer points to unknown type. in order to calculate the address where a[ i ] is  located by "a + (i * sizeof(a[ 0 ])"  the compiler needs to know the size of a single element of the array.

 - an unsigned int is 32-bit while unsigned char is 8-bit. so omitting the unsigned char would cause 4 bytes to be converted to an integer, what gives wrong numbers.

note, my compiler does not accept the cast you posted as "works" cause a[ i ]  still has an undefined size (the cast only determines the wished output of the a[ i ] but not the type of the array) and the address of a[ i ] cannot correctly calculated, because of that.

to solve the issue correctly you need to cast the void pointer to a byte pointer (see also code of jkr above). when the compiler knows the type of the pointer, operations like + or [] will compile properly.

unsigned char x[] = { 33, 34, 35, 36 };
void * a = x;
std::cout << (unsigned int)(*(unsigned char*)a+i);

Open in new window

the final cast to unsigned int is necessary to get the right operator<< selected which takes an int or unsigned int. otherwise the operator<<(std::ostream&, unsigned char) was used, which would not evaluate the std::hex manipulator, but would print the character code associated to the byte code.

to make all the code simpler you may use a byte buffer (pointer to unsigned char) instead of a void pointer as early as possible.

unsigned char * pbuf = (unsigned char *)getData();
std::cout << std::hex << std::setw(2) << std::right << std::setfill('0') << (int)pbuf[i];

Open in new window

it also needs two casts, but is much better readable.


Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now