Im trying to extract 4 bytes from hexadecimal value stored in int variable.
My idea is to "push" wanted byte to the end by using right shift operator( >> ) and then use AND operator with 0xFF value to get only last 8 bits of value. Its working fine with number values(73 for example) but its not working with values a-f(3f for example). I have tried using different formats for printf, like %02x , and i have also tried changing the mask for AND operator to 0x000000FF.
int variable = 0x12cd34f4;
char byte0, byte1, byte2, byte3;
byte0 = (char)(variable & 0xFF);
byte1 = (char)((variable >> 8) & 0xFF);
byte2 = (char)((variable >> 16) & 0xFF);
byte3 = (char)((variable >> 24) & 0xFF);
printf("%x\n",byte0);// prints fffffff4
printf("%x\n",byte1);// prints 34
printf("%x\n",byte2);//prints ffffffcd
printf("%x\n",byte3);//prints 12
I expected it to print f4 for byte0, 34 for byte1, cd for byte2 and 12 for byte3, but actual output for byte0 is fffffff4 and for byte2 ffffffcd. I dont understand why those F values are added, and how can i get rid of them.
char
can be signed or unsigned, that is system dependent (and, maybe, as well depending on compiler options).
In your case, it is obviously signed
. Values between 0x80
and 0xFF
(and not only those starting from 0xA0
!) have bit #7 set and are interpreted as signed value (e. g., 0xFF is -1, 0xF0 is -16, etc.).
When extending them to int
(that's what happens when calling printf()
), they are sign-extended (that's what the F
s come from) and thus retain their "interpreted value". printf()
, however, is told to treat them as unsigned again, so the -16 is represented as 0xFFFFFFF0
.
Either use unsigned char
resp. uint8_t
or add & 0xFF
when calling printf()
.
Just force char to be unsigned :
#include <stdio.h>
int main()
{
int variable = 0x12cd34f4;
unsigned char byte0, byte1, byte2, byte3;
byte0 = (char)(variable & 0xFF);
byte1 = (char)((variable >> 8) & 0xFF);
byte2 = (char)((variable >> 16) & 0xFF);
byte3 = (char)((variable >> 24) & 0xFF);
printf("%x\n",byte0);
printf("%x\n",byte1);
printf("%x\n",byte2);
printf("%x\n",byte3);
}
Compilation and execution :
pi@raspberrypi:/tmp $ gcc -pedantic -Wextra c.c
pi@raspberrypi:/tmp $ ./a.out
f4
34
cd
12
Note that the & 0xFF
are useless when a char has 8 bits
First, the %x
format specifier, without any modifiers, on its own, is for the type unsigned int
, which apparently on your system is 32-bits.
The most significant bits of the bytes F4
and CD
are 1. This is the sign bit, so it is sign-extended to the full 32-bits (hence the FFFFFF
), which are printed out.
Observe that when you print them out as %d
, you see the sign bit in play too:
-12
52
-51
18
To solve this, you can make the bytes of type unsigned char
, do a bitwise and on each printf
argument with 0xFF
, and use the correct format specifier for an unsigned char
in hex, which is %hhX
.
Your byte variables are declared as char
, which on most implementations is signed. When you pass these values to printf
, it doesn't know the exact type of what you pass in because it's a variadic function. So the char
arguments get promoted to int
. And because you have values which are negative, they get sign extended as part of the promotion.
Change the type of these variables to unsigned char
. When the positive values are then promoted to int
there will be no sign extension.
User contributions licensed under CC BY-SA 3.0