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

时光总嘲笑我的痴心妄想 提交于 2019-12-03 03:08:34

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!

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

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.

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 */
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!