tech_log: strtoul() result begins with ffffffff

Friday, August 7, 2009

strtoul() result begins with ffffffff

How is it possible that:
char bin[64];
char test[10] = "74";

bin[0] = strtoul (test, &e, 16);
printf("bin[0]=%#x\n", bin[0]);

is giving:
bin[0]=0x74

and if we put:
char test[10] = "84";

result printed is:
bin[0]=0xffffff84

Well, for all X in char test[10] = "X4"; that are less than 8, digit X starts with binary "0". For 8 and more, it will start with binary "1". Since we put "=" between char bin[64], thus SIGNED, and result that strtoul()  signed. Two things happen here:

1) Assignment conversion
An assignment conversion makes the value of the right operand have the same data type as the left operand.
(In assignment operations, the type of the value being assigned is converted to the type of the variable that receives the assignment. C allows conversions by assignment between integral and floating types, even if information is lost in the conversion.)
That means that our unsigned long return value of strtoul() becomes signed char.

2) Conversions from Unsigned Integral Types
An unsigned integer is converted to a shorter unsigned or signed integer by truncating the high-order bits, or to a longer unsigned or signed integer by zero-extending.
When the value with integral type is demoted to a signed integer with smaller size, or an unsigned integer is converted to its corresponding signed integer, the value is unchanged if it can be represented in the new type. However, the value it represents changes if the sign bit is set, as in the following example.

int j;
unsigned short k = 65533;

j = k;
printf_s( "%hd\n", j );   // Prints -3


Let's look at char. The highest positive value you can represent with one char is +127, i.e. 0x7F. Anything above this is represented as a negative. For example, 0x80 is actually -128, the biggest (in amplitude) negative number you can represent with char (and 0xFF is -1).

So, printing our result like this:
char test[10] = "80";
bin[0] = strtoul (test, &e, 16);
printf("bin[0]=%d\n", bin[0]);
drasko@Lenin:~/stuff$ ./test
bin[0]=-128

Makes more sense, because %#x switch was additional confusion, because it printed additional (starting) 3 bytes for negaitve number, putting them all into F.

RESOLUTION OF THE PROBLEM:
The buffer that takes result of assignment must be decleared as unsigned char, and not as signed char!

If we change
char bin[64];
to
unsigned char bin[64];
results will be good.




0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home