views:

508

answers:

2

Here's an odd problem that's been stumping me for a bit.

The program is written in C89, and it reads a file into a char* array 16 bytes at a time (using fread and a size of sizeof(char)). The file is fopen'd with the "rb" flags. The array is then passed into a function that basically takes the 16 hex values and sticks it into a string, each value seperated by a space.

Here's where the weirdness comes in. The function produces a nice hex dump, 16 bytes at a time, for a text file input that I have. But it screws up if I try it on a small bitmap image -- I end up with output in the string like ffffff88 instead of just 88.

The hex values are placed into the output string using sprintf("%02x ", input[i]); in a loop.

Why would this work properly for some files but not others?

+5  A: 

What you see is the result of sign extension from the char to int, using unsigned char * or casting to unsigned char before the cast to int is (implicitly?) performed should fix your problem.

rsp
+1  A: 

In C the char is treated as a signed value, unless you specify it as unsigned. It seems that when you pass parameters to a function, that when the parameter happens to be a char, it's 'padded out' to the size of a regular integer. If you don't clue the compiler in that this should be done in an unsigned way, 128 becomes 0xFFFFFF80, and so on.

So, the sign extension happens before the print formatter ever gets to look at the value. What this means is that

printf("%02X", (unsigned) input[i]);

won't solve your problem, as the value of input[i] will be sign extended, so all values from 128 to 255 are treated as -127 to -1 and become 0xFFFFFF80 to 0xFFFFFF, then cast, whereas

printf("%02X", ((unsigned char *) input)[i] );

will do the trick, but is kind of ungainly and hard to read. Best to make the type of input[] be unsigned char in the first place.

JustJeff