user1871869
user1871869

Reputation: 3367

Grabbing n bits from a byte

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!

Upvotes: 27

Views: 77688

Answers (7)

Vigor
Vigor

Reputation: 1

I think there is a much simpler way to do what you want. You only need the & "and" operator.

Basically, if you want the 5 most significant bits, all you have to do is add them up. 128+64+32+16+8 = 248 or the 3 least significant bits would be 4+2+1=7. Then use the and operator ( & ) with your variable and the total to assign those bits to a new variable.

int main()
{
    unsigned char c = 42;  //sum of 3rd bit + 5th bit + 7th bit
    int first5 = c & 248; //sum of bits 1-5
    int last3 = c & 7; // sum of bits 6-8
    cout << "first 5 " << first5 << " last 3 " << last3 << endl;
    cout << "OR 5 most significant bits " << first5 << endl;
    cout << "and 3 least significant bits " << last3 <<endl;
    return 0;
}

But, you can also use this to grab one individual bit or any combination of bits.

For instance...

int threenfive = c&40; //would extract the 3rd bit and 5th bit

because the 3rd bit = 32 and the 5th = 8 and the sum of the two = 40.

Upvotes: 0

rici
rici

Reputation: 241721

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 review 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.

Upvotes: 29

Mats Petersson
Mats Petersson

Reputation: 129374

"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;

Upvotes: 20

wirrbel
wirrbel

Reputation: 3299

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.

Upvotes: 9

gaborsch
gaborsch

Reputation: 15758

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

Upvotes: 13

meyumer
meyumer

Reputation: 5064

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.

Upvotes: 2

Dave
Dave

Reputation: 46259

just get rid of the 8* in your code.

int input = 42;
int high3 = input >> 5;
int low5 = input & (32 - 1); // 32 = 2^5
bool isBit3On = input & 4; // 4 = 2^(3-1)

Upvotes: 1

Related Questions