I'm trying to read in a line of characters, then print out the hexadecimal equivalent of the characters.
For example, if I have a string that is "0xc0 0xc0 abc123"
, where the first 2 characters are c0
in hex and the remaining characters are abc123
in ASCII, then I should get
c0 c0 61 62 63 31 32 33
However, printf
using %x
gives me
ffffffc0 ffffffc0 61 62 63 31 32 33
How do I get the output I want without the "ffffff"
? And why is it that only c0 (and 80) has the ffffff
, but not the other characters?
Try something like this:
Which produces this:
You can use
hh
to tellprintf
that the argument is an unsigned char. Use0
to get zero padding and2
to set the width to 2.x
orX
for lower/uppercase hex characters.Edit: If readers are concerned about 2501's assertion that this is somehow not the 'correct' format specifiers I suggest they read the
printf
link again. Specifically:As for his point about signed vs unsigned, in this case it does not matter since the values must always be positive and easily fit in a signed int. There is no signed hexideximal format specifier anyway.
Edit 2: ("when-to-admit-you're-wrong" edition):
If you read the actual C11 standard on page 311 (329 of the PDF) you find:
Indeed, there is type conversion to int. Also you can force type to char by using %hhx specifier.
In most cases you will want to set the minimum length as well to fill the second character with zeroes:
ISO/IEC 9899:201x says:
You can create an unsigned char:
Printing it will give
C5
and notffffffc5
.Only the chars bigger than 127 are printed with the
ffffff
because they are negative (char is signed).Or you can cast the
char
while printing:You are seeing the
ffffff
becausechar
is signed on your system. In C, vararg functions such asprintf
will promote all integers smaller thanint
toint
. Sincechar
is an integer (8-bit signed integer in your case), your chars are being promoted toint
via sign-extension.Since
c0
and80
have a leading 1-bit (and are negative as an 8-bit integer), they are being sign-extended while the others in your sample don't.Here's a solution:
This will mask out the upper bits and keep only the lower 8 bits that you want.
You are probably printing from a signed char array. Either print from an unsigned char array or mask the value with 0xff: e.g. ar[i] & 0xFF. The c0 values are being sign extended because the high (sign) bit is set.