Reputation: 2890
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.
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.
Upvotes: 21
Views: 112285
Reputation: 2278
I know this is a very old question but obviously still relevent. Here is my contribution using the ((1 << N)-1)
trick for getting the desrired bitmask. It wasn't asked here, but I'll offer up both ways to extract and store the desired bits. Let's say that someValue
holds a 2-bit field called foo
at bits 0-1 and a 3-bit field called bar
at bits 3-5. Let's further assume you've got a code generator to hardcode the offsets into the setters and getters to simplify the interface because of course you do.
uint8_t someValue = 0;
inline uint8_t getFoo() const {
//start bit = 0, size in bits = 2, end = 2
uint8_t mask = (1 << (2 - 0)) - 1; //end-start-1
return (someValue >> 0) & mask; //shift back by start
}
inline void setFoo(uint8_t foo) {
someValue &= ~(((1 << (2 - 0)) - 1) << 0); //end-start-1, shift by start
someValue |= foo << 0; //shift by start
}
inline uint8_t getBar() const {
//start bit = 3, size in bits = 3, end = 6
uint8_t mask = (1 << (6 - 3)) - 1; //end-start-1
return (someValue >> 3) & mask; //shift back by start
}
inline void setBar(uint8_t bar) {
someValue &= ~(((1 << (6 - 3)) - 1) << 3); //end-start-1, shift by start
someValue |= bar << 3; //shift by start bit
}
Upvotes: 0
Reputation: 31
//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))
Upvotes: 3
Reputation: 717
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
Upvotes: 2
Reputation: 100
unsigned int extract_n2mbits(unsigned int x, int n, int m)
{
unsigned int mask, tmp;
if (n < m) {
n = n + m;
m = n - m;
n = n - m;
}
mask = 1 << (n - m + 1);
tmp = m;
while (tmp > 1) {
mask = mask << 1 | 1 << (n - m + 1);
tmp = tmp - 1;
}
return ((x & mask) >> (n - m + 1));
}
Upvotes: 0
Reputation: 1769
// This is the main project file for VC++ application project
// generated using an Application Wizard.
#include "stdafx.h"
#using <mscorlib.dll>
using namespace System;
void fun2(int *parr)
{
printf(" size of array is %d\n",sizeof(parr));
}
void fun1(void)
{
int arr[100];
printf(" size of array is %d\n",sizeof(arr));
fun2(arr);
}
int extractBit(int byte, int pos)
{
if( !((pos >= 0) && (pos < 16)) )
{
return 0;
}
return ( ( byte & (1<<pos) ) >> pos);
}
int extractBitRange(int byte, int startingPos, int offset)
{
if( !(((startingPos + offset) >= 0) && ( (startingPos + offset) < 16)) )
{
return 0;
}
return ( byte >> startingPos ) & ~(0xff << (offset + 1));
}
int _tmain()
{
// TODO: Please replace the sample code below with your own.
int value;
signed int res,bit;
signed int stPos, len;
value = 0x1155;
printf("%x\n",value);
//Console::WriteLine("Hello World");
//fun1();
for(bit=15;bit>=0;bit--)
{
res =extractBit(value,bit);
printf("%d",res);
}
stPos = 4;
len = 5;
res = extractBitRange(value, stPos, len);
printf("\n%x",res);
return 0;
}
Upvotes: 1
Reputation: 5226
void f(short int last, short int first, short int myNr){
//construct mask for last bits
short int mask=0;
for(int i=0;i<last;i++)
{ mask+=1;
mask<<1;}
short int aux= myNr;
aux=aux&mask; // only last bits are left
//construct mask for first bits
mask=0;
for(int i=0;i<first;i++)
{ mask+=0x8000h;
mask>>1;}
aux=myNr;
aux&=mask;
aux>>last; // only first bits are left and shifted
}
you can add parameters to get the values out or something
Upvotes: 0
Reputation: 13356
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.
Upvotes: 12
Reputation: 726479
There are two building blocks that you need to know to build this yourself:
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+1
st position, and all zeros after it. Subtracting one gives you the mask that you need.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.
Upvotes: 30
Reputation: 52519
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.
Upvotes: 18