How can I access a specific group of bits from a variable?

17,773

Solution 1

You would do this with a series of 2 bitwise logical operations.

[[Terminology MSB (msb) is the most-significant-bit; LSB (lsb) is the least-significant-bit. Assume bits are numbered from lsb==0 to some msb (e.g. 31 on a 32-bit machine). The value of the bit position i represents the coefficient of the 2^i component of the integer.]]

For example if you have int x, and you want to extract some range of bits x[msb..lsb] inclusive, for example a 4-bit field x[7..4] out of the x[31..0] bits, then:

  1. By shifting x right by lsb bits, e.g. x >> lsb, you put the lsb bit of x in the 0th (least significant) bit of the expression, which is where it needs to be.

  2. Now you have to mask off any remaining bits above those designated by msb. The number of such bits is msb-lsb + 1. We can form a bit mask string of '1' bits that long with the expression ~(~0 << (msb-lsb+1)). For example ~(~0 << (7-4+1)) == ~0b11111111111111111111111111110000 == 0b1111.

Putting it all together, you can extract the bit vector you want with into a new integer with this expression:

(x >> lsb) & ~(~0 << (msb-lsb+1))

For example,

int x = 0x89ABCDEF;
int msb = 7;
int lsb = 4;
int result = (x >> lsb) & ~(~0 << (msb-lsb+1));
//      ==   0x89ABCDE  & 0xF
//      ==   0xE (which is x[7..4])

Make sense?

Happy hacking!

Solution 2

If you're dealing with a primitive then just use bitwise operations:

int bits = 0x0030;
bool third_bit = bits & 0x0004;  // bits & 00000100
bool fifth_bit = bits & 0x0010;  // bits & 00010000

If x can be larger than a trivial primitive but is known at compile-time then you can use std::bitset<> for the task:

#include<bitset>
#include<string>

// ...
std::bitset<512> b(std::string("001"));
b.set(2, true);
std::cout << b[1] << ' ' << b[2] << '\n';

std::bitset<32>  bul(0x0010ul);

If x is not known at compile-time then you can use std::vector<unsigned char> and then use bit-manipulation at runtime. It's more work, the intent reads less obvious than with std::bitset and it's slower, but that's arguably your best option for x varying at runtime.

#include<vector>

// ...
std::vector<unsigned char> v(256);
v[2] = 1;
bool eighteenth_bit = v[2] & 0x02;  // second bit of third byte

Solution 3

work on bits with &, |. <<, >> operators. For example, if you have a value of 7 (integer) and you want to zero out the 2nd bit:

7 is 111

(zero-ing 2nd bit AND it with 101 (5 in decimal))

111 & 101 = 101 (5)

here's the code:

#include <stdio.h>

main ()
{
    int x=7;

    x= x&5;
    printf("x: %d",x);

}

You can do with other operators like the OR, shift left, shift right,etc.

Share:
17,773
user537670
Author by

user537670

Updated on July 27, 2022

Comments

  • user537670
    user537670 almost 2 years

    I have a variable with "x" number of bits. How can I extract a specific group of bits and then work on them in C?