Reputation: 884
I've run into a slightly strange problem - I have a char array that I want to output as hex. I don't mind casting as int, but when I do, a lot of f's are added in front of some of the numbers. I have this code do my output for me:
for (int i = 0; i<(bmp.BytesPerRow*bmp.Height);i++) // once per color per pixel
{
if(i%3==0) // one line between each pixel
{
cout << "\n";
}
int tmp = (int) bmp.Raster[i];
cout << "\nbmp.Raster[" << i << "]": " << hex << tmp;
}
and my output looks like this:
bmp.Raster[0]: ffffffff
bmp.Raster[1]: ffffffff
bmp.Raster[2]: ffffffff
bmp.Raster[3]: 40
bmp.Raster[4]: 20
bmp.Raster[5]: ffffffe0
bmp.Raster[6]: 40
bmp.Raster[7]: ffffffe0
bmp.Raster[8]: 20
etc...
and frankly I don't get it. I could understand if it was
ff
ff
ff
40
20
e0
etc...
and I could understand if the f's were appended to everything (I'd figure it was an artifact of the casting process and just discard the first 6 outputs) but only to some? I don't get it.
Additional info:
bmp.Raster is from the class CRaster[1] kindly provided by Juan Soulie
IDE is Microsoft Visual C++ 2010 Express which automatically does #include "tchar.h", but I've tried commenting that library out and the oddity persists.
[1]http://www.cplusplus.com/files/winbmp.zip
EDIT: Some of you are providing suggestions for solutions - and I appreciate that - but mostly I'm asking here if somebody knows what the devil is going on?
EDIT AGAIN: Problem was resolved by James Kanze.
The loop has been changed to:
for (int i = 0; i<(bmp.BytesPerRow*bmp.Height);i++) // once per color per pixel
{
if(i%3==0) // one line between each pixel
{
cout << "\n";
}
uint8_t tmp0 = (uint8_t)bmp.Raster[i];
uint16_t tmp1 = (uint16_t)tmp0;
cout << "\nbmp.Raster[" << i << "]": " << hex << tmp1;
}
and the output is now correct.
Upvotes: 1
Views: 418
Reputation: 153929
The problem is that plain char's on your machine are signed. (If you're not too concerned about portability, both g++ and VC++ have options to make plain char unsigned.) You need to first cast the char to unsigned char, then cast the unsigned char to int. Or, if you can change the data structures you're outputting, change them to use unsigned char; that seems more appropriate for things like bitmaps anyway.
Upvotes: 1
Reputation: 680
Use this line:
unsigned char tmp = bmp.Raster[i];
instead of:
int tmp = (int) bmp.Raster[i];
It might works.
Upvotes: 0
Reputation: 8694
Not this:
int tmp = (int) bmp.Raster[i];
but this:
int tmp = (unsigned int) bmp.Raster[i]; // OR
unsigned int tmp = bmp.Raster[i];
might work.
When you cast the byte value to a (signed) int, the sign bit (the high-order bit) of the byte gets propagated to fill the upper part of the integer. So a byte of (say) 0x80 becomes an int of something like 0xffffff80. Unsigned arithmetic yields the behavior you want.
Upvotes: 1