I have in C language hex numbers defined in string:
char chars[] = "\xfb\x54\x9c\xb2\x10\xef\x89\x51\x2f\x0b\xea\xbb\x1d\xaf\xad\xf8";
Then I want to compare the values with another. It is not working and if I print the value like:
printf("%02x\n", chars[0]);
it writes fffffffb. Why is that and how to get fb value exactly?
This is because of the sign extension.
Change
printf("%02x\n", chars[0]);
to
printf("%02x\n", (unsigned char)chars[0]);
The %x format specifier will read 4 bytes on 32bit machine. As you have declared chars as the character array, when fetching the value fb(negative value) will be sign extended as fffffffb, where the MSB of fb is set to all other bits before it.
Refer this for more details sign extension
If you would have declared char chars[] as unsigned char chars[] then the print would have been as expected.
As per the standard mentioning regarding the %x format specifier with fprintf()
o,u,x,XThe unsigned int argument is converted to unsigned octal (o), unsigned decimal (u), or unsigned hexadecimal notation (x or X) in the style dddd; [...]
So, the expected type of argument to %x is unsigned int.
Now, printf() being a variadic function, only default promotion rule is applied to its arguments. In your code, chars being an array of type char (signedness of which is implementation dependent), in case of
printf("%02x\n", chars[0]);
the value of chars[0] get promoted to an int which is not the expected type for %x. Hence, the output is wrong, as int and unsigned int are not the same type. [Refer §6.7.2, C11]. So, without an explicit cast like
printf("%02x\n", (unsigned int)chars[0]);
it invokes undefined behaviour.
FWIW, if you're having a C99 supported compiler, you can make use of the hh length modifier to work around this, like
printf("%02hhx\n", (unsigned char)chars[0]);
It's because of sign extension.
This will work as you expect:
printf("%02x\n", (unsigned char)chars[0]);