8

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?

Jamal
  • 763
  • 7
  • 22
  • 32
user537670
  • 821
  • 6
  • 21
  • 42
  • 1
    You need to more specific. What exactly are you trying to do? "Work on them" could be anything. – EboMike Dec 11 '10 at 03:50
  • 1
    You also might want to clarify what you mean by "extract". Do you want to modify them in place or simply get their value and do some calculation based on the result? – jonmorgan Dec 11 '10 at 03:55
  • Does searching for "bitmask" help point you in the right direction? – momeara Dec 11 '10 at 04:04
  • actually i need to compare a group of bits from a variable with another group of bits in a variable defined by me. – user537670 Dec 11 '10 at 04:28
  • possible duplicate of [How do you set, clear and toggle a single bit in C?](http://stackoverflow.com/questions/47981/how-do-you-set-clear-and-toggle-a-single-bit-in-c) – Martin York Dec 11 '10 at 04:48

4 Answers4

25

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!

Jan Gray
  • 3,454
  • 19
  • 15
5

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
wilhelmtell
  • 57,473
  • 20
  • 96
  • 131
2

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.

Neilvert Noval
  • 1,655
  • 2
  • 15
  • 21
0

You can use bitfields in a union:

typedef union {
unsigned char value;
struct { unsigned b0:1,b1:1,b2:1,b3:1,b4:1,b5:1,b6:1,b7:1; } b;
struct { unsigned b0:2,b1:2,b2:2,b3:2; } b2;
struct { unsigned b0:4,b1:4; } b4;
} CharBits;


CharBits b={0},a={0};
printf("\n%d",b.value);
b.b.b0=1; printf("\n%d",b.value);
b.b.b1=1; printf("\n%d",b.value);
printf("\n%d",a.value);
a.b4.b1=15; printf("\n%d",a.value); /* <- set the highest 4-bit-group with one statement */
user411313
  • 3,930
  • 19
  • 16