Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to extract specific bits from a number in C?

I need to extract specific part (no of bits) of a short data type in C.

For Example I have a binary of 52504 as 11001101000 11000 and I want First 6 ( FROM LSB --> MSB i.e 011000 decimal 24) bits and rest of 10 bits ( 11001101000 decimal 820).

Similarly I want this function to be too generalized to extract specific no of bits given "start" and "end" (i.e chunks of bits equivalent with some decimal value).

I checked other posts, but those were not helpful, as given functions are not too much generalized.

I need something that can work for short data type of C.

Edit

I am having the short array of size 2048 bytes. Where each Pixel is of 10 bits. So my 16 bit consisting each byte occupying some time 2 pixels data, sometimes 3 pixels data.

Like

( PIXEL : 0,1 ) 10 BITS + 6 BITS

then ( PIXEL : 1,2,3 ) 4 BITS ( 1st pixels remaining bits ) + 10 BITS + 2 BITS.

and so on ..this pattern continues ... So, all I want to extract each pixel and make an entire array of having each pixels to be occupied wholy in on WHOLE BYTE ( of 16 bits ) like.. 1 byte should contain 1 DATA PIXEL, the other BYTE should contain other PIXEL value in whole 16 bits and so on so forth.

like image 998
Usman Avatar asked Apr 10 '12 14:04

Usman


People also ask

How do you find the bit of an integer?

Here we create a mask, apply the mask to n, and then right shift the masked value to get just the bit we want. We could write it out more fully as: int mask = 1 << k; int masked_n = n & mask; int thebit = masked_n >> k; You can read more about bit-masking here.

Can C manipulate bits?

Bit manipulation is the act of algorithmically manipulating bits or other pieces of data shorter than a byte. C language is very efficient in manipulating bits.

How do you read a byte from a bit?

You can mask out the bits you want from a byte using bitwise AND. In general, to test for individual bits, C has bitwise operators. Example: SO: C/C++ check if one bit is set in, i.e. int variable.


5 Answers

There are two building blocks that you need to know to build this yourself:

  • Getting N least significant bits requires constructing a bit mask with N ones at the end. You do it like this: ((1 << N)-1). 1 << N is 2 ^ N: it has a single 1 at the N+1st position, and all zeros after it. Subtracting one gives you the mask that you need.
  • Dropping M least significant bits is a simple shift to the right: k >> M

Now your algorithm for cutting out from M to N becomes a two-step process: you shift the original value M bits to the right, and then perform a bit-wise AND with the mask of N-M ones.

#define LAST(k,n) ((k) & ((1<<(n))-1))
#define MID(k,m,n) LAST((k)>>(m),((n)-(m)))

int main() {
    int a = 0xdeadbeef;
    printf("%x\n",  MID(a,4,16));
    return 0;
}

This fragment cuts out bits from 4, inclusive, to 16, exclusive, and prints bee when you run it. Bits are numbered from zero.

like image 73
Sergey Kalinichenko Avatar answered Oct 20 '22 05:10

Sergey Kalinichenko


unsigned short extract(unsigned short value, int begin, int end)
{
    unsigned short mask = (1 << (end - begin)) - 1;
    return (value >> begin) & mask;
}

Note that [begin, end) is a half open interval.

like image 28
Andreas Brinck Avatar answered Oct 20 '22 06:10

Andreas Brinck


It can be done like this:

mask = ~(~0 << (end - start + 1));
value = (n >> start) & mask;

where n is the original integer and value is the extracted bits.

The mask is constructed like this:

1. ~0 = 1111 1111 1111 1111 1111 1111 1111 1111
2. ~0 << (end - start + 1) = 1111 1111 1111 1111 1100 0000 0000 0000
   // assuming we are extracting 14 bits, the +1 is added for inclusive selection
   // ensure that end >= start
3. ~(~0 << (end - start + 1)) = 0000 0000 0000 0000 0011 1111 1111 1111

Now n is shifted right by start bits to align the desired bits to the left. Then a bitwise AND gives the result.

like image 10
Sufian Latif Avatar answered Oct 20 '22 05:10

Sufian Latif


//To get value from specific position 'pos' to 'pos+offset' in number 'value'

#define bitGet(value, offset, pos) (((1ull << offset) - 1) & (value >> (pos - 1)))

//Set value 'newval' from position 'pos' to 'pos+offset' in number 'value'

#define bitSet(value, offset, pos, newval)  \
(~(((1ull << offset) - 1) << (pos - 1)) & value) | ((((1ull << offset) - 1) & newval) << (pos - 1))
like image 3
Neeta Avatar answered Oct 20 '22 05:10

Neeta


Although its a very old question, I would like to add a different solution. Using macros,

/* Here, startBit : start bit position(count from LSB) endBit : end bit position(count from LSB) .NOTE: endBit>startBit number : the number from which to extract bits maxLength:the total bit size of number. */ `

#include <stdio.h>
#define getnbits(startBit,endBit,number,maxLength) \
  ( number &  ( (~0U >> (maxLength-endBit)) & (~0U << startBit) )  ) 

int main()
{
    unsigned int num=255;
    unsigned int start=1,end=5,size=sizeof(num)*8;

    printf("Inputs : %d %d %d %d \n ",start,end,num,size);
    printf("Input number : %d\n",num);

    if(end>start)
    {
        int result = getnbits(start,end,num,size-1);
        printf("Output : %u\n\n",result);
    }
    else
        printf("Error : EndBit is smaller than starBit!\n\n");

    return 0;
}

`

Output : Inputs : 1 5 255 32
Input number : 255
Output : 62

Here, 255 = 11111111 and 62 = 00111110

like image 2
PraveenMax Avatar answered Oct 20 '22 04:10

PraveenMax