开发者

Casting char * as int gives strange error

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]:开发者_Go百科 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.


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.


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.


Use this line:

unsigned char tmp = bmp.Raster[i];

instead of:

int tmp = (int) bmp.Raster[i];

It might works.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜