Grabbing n bits from a byte

59,903

Solution 1

Integers are represented inside a machine as a sequence of bits; fortunately for us humans, programming languages provide a mechanism to show us these numbers in decimal (or hexadecimal), but that does not alter their internal representation.

You should revise the bitwise operators &, |, ^ and ~ as well as the shift operators << and >>, which will help you understand how to solve problems like this.

The last 3 bits of the integer are:

x & 0x7

The five bits starting from the eight-last bit are:

x >> 3    // all but the last three bits
  &  0x1F // the last five bits.

Solution 2

"grabbing" parts of an integer type in C works like this:

  1. You shift the bits you want to the lowest position.
  2. You use & to mask the bits you want - ones means "copy this bit", zeros mean "ignore"

So, in you example. Let's say we have a number int x = 42;

first 5 bits:

(x >> 3) & ((1 << 5)-1);

or

(x >> 3) & 31;

To fetch the lower three bits:

(x >> 0) & ((1 << 3)-1)

or:

x & 7;

Solution 3

Say you want hi bits from the top, and lo bits from the bottom. (5 and 3 in your example)

top = (n >> lo) & ((1 << hi) - 1)
bottom = n & ((1 << lo) - 1)

Explanation:

For the top, first get rid of the lower bits (shift right), then mask the remaining with an "all ones" mask (if you have a binary number like 0010000, subtracting one results 0001111 - the same number of 1s as you had 0-s in the original number).

For the bottom it's the same, just don't have to care with the initial shifting.

top = (42 >> 3) & ((1 << 5) - 1) = 5 & (32 - 1) = 5 = 00101b
bottom = 42 & ((1 << 3) - 1) = 42 & (8 - 1) = 2 = 010b

Solution 4

You could use bitfields for this. Bitfields are special structs where you can specify variables in bits.

typedef struct {
  unsigned char a:5;
  unsigned char b:3;
} my_bit_t;

unsigned char c = 0x42;
my_bit_t * n = &c;
int first = n->a;
int sec = n->b;

Bit fields are described in more detail at http://www.cs.cf.ac.uk/Dave/C/node13.html#SECTION001320000000000000000

The charm of bit fields is, that you do not have to deal with shift operators etc. The notation is quite easy. As always with manipulating bits there is a portability issue.

Solution 5

int x = (number >> 3) & 0x1f;

will give you an integer where the last 5 bits are the 8-4 bits of number and zeros in the other bits.

Similarly,

int y = number & 0x7;

will give you an integer with the last 3 bits set the last 3 bits of number and the zeros in the rest.

Share:
59,903
user1871869
Author by

user1871869

Updated on July 14, 2022

Comments

  • user1871869
    user1871869 almost 2 years

    I'm having a little trouble grabbing n bits from a byte.

    I have an unsigned integer. Let's say our number in hex is 0x2A, which is 42 in decimal. In binary it looks like this: 0010 1010. How would I grab the first 5 bits which are 00101 and the next 3 bits which are 010, and place them into separate integers?

    If anyone could help me that would be great! I know how to extract from one byte which is to simply do

    int x = (number >> (8*n)) & 0xff // n being the # byte
    

    which I saw on another post on stack overflow, but I wasn't sure on how to get separate bits out of the byte. If anyone could help me out, that'd be great! Thanks!