Salim
Salim

Reputation: 373

Extracting a particular range of bits and find number of zeros between them in C

I want to extract a particular range of bits in an integer variable.

For example: 0xA5 (10100101)

I want to extract from bit2 to bit5. i.e 1001 to a variable and count number of zeros between them.

I have another variable which give the starting point, which means in this case the value of the variable is 2. So the starting point can be find by 0xA5 >> 2. 5th bit position is a random position here..means it can be 6 or 7. The main idea is whichever bit is set to 1 after 2nd bit. I have to extract that..

How can I do rest of the part ?

Upvotes: 1

Views: 613

Answers (6)

Salim
Salim

Reputation: 373

int32_t do_test(int32_t value, int32_t offset)
{
    int32_t _zeros = 1;
    value >>= offset;    

    int i = 1;

    while(1) {
        if((value >> i) % 2 == 0) {
            _zeros += 1;
            i++;
        } else {
            break;
        }
    }
}

Upvotes: 1

Ajay Brahmakshatriya
Ajay Brahmakshatriya

Reputation: 9203

Assuming you are dealing with unsigned int for your variable. You will have to construct the appropriate mask.

Suppose you want the bits from position x to position y, there need to be y - x + 1 1s in the mask.

You can get this by -

int digits = y - x + 1;
unsigned int mask = 1u << digits - 1;

Now you need to remove the lower x bits from the initial number, which be done by -

unsigned int result = number >> x;

Finally apply the mask to remove the upper bits -

result = result & mask;

Upvotes: 2

Some programmer dude
Some programmer dude

Reputation: 409356

If you want bits from the offset X then shift right by X.

If you want Y bits, then then mask (after the shift) will be 2 to the power of Y minus one (for your example with four bits, 2 to the power of 4 is 16, minus one is 15 which is 1111 binary). This can be dome by using left-shifting by Y bits and subtracting 1.

However, the masking isn't needed if you want to count the number of zeros in the wanted bits, only the right shift. Loop Y times, each time shifting a 1 left one step, and check using bitwise and if the value is zero. If it is then increment a counter. At the end of the loop the counter is the number of zeros.


To put it all in code:

// Count the number of zeros in a specific amount of bits starting at a specific offset
// value is the original value
// offset is the offset in bits
// bits is the number of bits to check
unsigned int count_zeros(unsigned int value, unsigned int offset, unsigned int bits)
{
    // Get the bits we're interested in the rightmost position
    value >>= offset;

    unsigned int counter = 0;  // Zero-counter
    for (unsigned int i = 0; i < bits; ++i)
    {
        if ((value & (1 << i)) == 0)
        {
            ++counter;  // Bit is a zero
        }
    }

    return counter;
}

To use with the example data you have:

count_zeros(0xa5, 2, 4);

The result should be 2. Which it is if you see this live program.

Upvotes: 1

Nark
Nark

Reputation: 474

You could use a mask and the "&" (AND) operation:

a = 0xA5;
a = a >> OFFSET; //OFFSET 
mask = 0x0F; // equals 00001111
a = a & mask; 

In your example a = 0xA5 (10100101), and the offset is 2.

  • a >> 2 a now equals to 0x29 (00101001)
  • a & 0x0F (00101001 AND 00001111) = 00001001 = 0x09

Upvotes: 1

Korsarq
Korsarq

Reputation: 795

int result = (0xA5 >> 2) & 0x0F;

Truth table for the & operator

 |    INPUTS  | OUTPUT |
 -----------------------
 |  0   |  0  |    0   |
 |  0   |  1  |    0   |
 |  1   |  0  |    0   |  
 |  1   |  1  |    1   |
 -----------------------  

Upvotes: 0

Ivan  Ivanov
Ivan Ivanov

Reputation: 2106

In this example we put 0 or 1 values into array. After that you can treat array as you like.

#include <stdio.h>
#include <stdint.h>

int main(int argc, char **argv) {
    uint8_t value = 0xA5;
    unsigned char bytes[8];
    unsigned char i;

    for (i = 0; i < 8; i++) {
        bytes[i] = (value & (1 << i)) != 0 ? 1 : 0;
    }

    for (i = 0; i < 8; i++) {
        printf("%d", bytes[i]);
    }

    return 0;
}

Upvotes: 1

Related Questions