How to extract bytes from an int variable(hexadecimal value stored in int variable)?

1

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.

c
hex
bitwise-operators
asked on Stack Overflow Feb 7, 2019 by John Doe

4 Answers

3

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 Fs 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().

answered on Stack Overflow Feb 7, 2019 by glglgl
2

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

answered on Stack Overflow Feb 7, 2019 by bruno
2

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.

answered on Stack Overflow Feb 7, 2019 by Govind Parmar • edited Feb 7, 2019 by Govind Parmar
2

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.

answered on Stack Overflow Feb 7, 2019 by dbush • edited Feb 7, 2019 by dbush

User contributions licensed under CC BY-SA 3.0