27

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!

1
  • First 5 (MSB) bits of 42 are 00000 because int is always more than 1 byte. Also, there is no such thing as unsigned integer that has the decimal form of a hex. int a = 0x2A; is the same as writing int a = 42; Commented Mar 6, 2013 at 19:06

7 Answers 7

29

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. 
Sign up to request clarification or add additional context in comments.

2 Comments

How does this compare performance-wise with just storing the two sub-ints as two 32 bit integers? The extraction is going to take some time, but is it 32 operations slower?
@InspiredOne: Questions like that are impossible to answer precisely in the abstract, but it's obvious that it improves memory usage (by a factor of eight relative to two 32-bit integers, or by a factor of two relative to two bytes) which improves cache performance, memory throughput, and bandwidth if relevant (transmission time or secondary storage). Since the CPU cost is trivial compared to any of these factors, the compressed data will normally be faster provided that you need many instances; it's not worth doing for a single pair of variables (but it doesn't hurt much either).
20

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

Comments

13

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 

Comments

9

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.

Comments

2

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.

Comments

1

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) 

Comments

0

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.