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)
Who is Participating?
>>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.
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*
Cloud Class® Course: MCSA MCSE Windows Server 2012

This course teaches how to install and configure Windows Server 2012 R2.  It is the first step on your path to becoming a Microsoft Certified Solutions Expert (MCSE).

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

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
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.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.