stillAFanOfTheSimpsons
stillAFanOfTheSimpsons

Reputation: 173

Mask and extract bits in C

I've been looking at posts about masks, but I still can't get my head around how to extract certain bits from a number in C.

Say if we have an integer number, 0001 1010 0100 1011, its hexadecimal representation is 0x1A4B, right? If I want to know the 5th to 7th number, which is 101 in this case, shall I use int mask= 0x0000 1110 0000 0000, int extract = mask&number?

Also, how can I check if it is 101? I guess == won't work here...

Upvotes: 5

Views: 46493

Answers (7)

alk
alk

Reputation: 70981

Assuming the GCC extension 0b to define binary literals:

int number = 0b0001101001001011; /* 0x1A4B */
int mask =   0b0000111000000000; /* 0x0E00 */
/* &'ed:     0b0000101000000000;    0x0A00 */
int extract = mask & number;     /* 0x0A00 */

if (extract == 0b0000101000000000)
/* Or if 0b is not available:
if (extract == 0x0a00 ) */
{
  /* Success */
}
else
{
  /* Failure */
}

Upvotes: 5

Ruslan Gerasimov
Ruslan Gerasimov

Reputation: 1782

First of all, your calculation for bits 7-6-5 is incorrect. You stated it was 101, but it is 010 (for x1a43).

Second of all, to get these bits (the value represented by these bits) you should do &0xE0.

int my_bits_from_5to7 = number & 0xE0;

Upvotes: 0

hitesh
hitesh

Reputation: 378

shall I use int mask= 0x0000 1110 0000 0000, int extract = mask&number?-

Yes, you can do this.

Also, how can I check if it is 101?

Sure you can check this- 0000 1010 0000 0000 which is 1280 in int.

extract== 1280

Upvotes: 0

Baldrickk
Baldrickk

Reputation: 4409

First, the digits in binary are (usually) counted from the right (10th and 12th digit) or you say 5th and 7th most significant digits.

int mask =  0x0E00;  // 0000 1110 0000 0000;
int extract = mask & number;

results in:

extract = 0000 1010 0000 0000

You can do

if (extract == 0x0A00 /*0000 1010 0000 0000*/){}

to test, or:

if (( extract >> 9 ) == 0x05){}

Both of the statements in the if will return true with your sample number.

Usually with a mask you will find yourself testing a single digit. You could use a function like this to test it:

bool digit_value( unsigned int number, unsigned int digit)
{
    return (1 << digit) & number;
}

int main()
{
    unsigned int number = 0x1A4B;
    int should_be_three = 0;
    should_be_three +=  digit_value(number, 10);
    should_be_three += !digit_value(number, 11);
    should_be_three +=  digit_value(number, 12);
    printf("%s", (should_be_three == 3?"it worked":"it didn't work"));
    return 0;
}

Upvotes: 1

sirlark
sirlark

Reputation: 2207

You need to mask and shift. Either shift the value you are comparing to, or the value you are comparing. I find it easier to think about by shifting the value you are comparing to. So if you're trying to extract the 5th to 7th digits (from the left), you shift right 9 positions (16-7) so that the 7th digit is now the rightmost, then apply 0x7 (111 in binary) as a mask to get only the rightmost three binary digits

int i = 0x1A4B;
if (((i >> 9) & 0x07) == 0x05) { // 0x05 = 101 in binary
    //do what you need to
}

Upvotes: 1

noktigula
noktigula

Reputation: 445

It may be simpler to check bits one-by-one, not all at once. At first, you create mask for interested bit:

int fifthBitMask = 1 << 4;
int fifthBitResult = number & fifthBitMask;

int seventhBitMask = 1 << 6;
int seventhBitResult = number & seventhBitMask;

Now, you can compare results with zero OR with mask. Comparing with zero can be omitted, so you can just use simple if:

if (fifthBitResult && seventhBitResult)
{
    //your code here
}

Also, you can compare with masks. After operation &, in result will set only bits, which was set in mask. So, it could like this: if (fifthBitResult == fifthBitMask && seventhBitResult == seventhBitMask) { // your code here }

So, if result of operation is equals to mask, you can do this with one operation:

int mask = 0x5 << 4; // 0x5 is hex representation of 101b
int result = number & mask;
if (result == mask)
{
    // your code here
}

Upvotes: 0

PandaConda
PandaConda

Reputation: 3516

Masking is done by setting all the bits except the one(s) you want to 0. So let's say you have a 8 bit variable and you want to check if the 5th bit from the is a 1. Let's say your variable is 00101100. To mask all the other bits we set all the bits except the 5th one to 0 using the & operator:

00101100 & 00010000

Now what this does is for every bit except the 5th one, the bit from the byte on the right will be 0, so the result of the & operation will be 0. For the 5th bit, however, the value from the right bit is a 1, so the result will be whatever the value of hte 5th bit from the left byte is - in this case 0:

Now to check this value you have to compare it with something. To do this, simply compare the result with the byte on the right:

result = (00101100 & 00010000) == 00000000

To generalize this, you can retrieve any bit from the lefthand byte simply by left-shifting 00000001 until you get the bit you want. The following function achieves this:

int getBit(char byte, int bitNum)
{
    return (byte & (0x1 << (bitNum - 1)))
}

This works on vars of any size, whether it's 8, 16, 32 or 64 (or anything else for that matter).

Upvotes: 6

Related Questions