I have a function to extract a single bit from a number:
int getBit (int value, int position) {
return value & (1 << position));
}
But how do I do it for a range (both for signed and unsigned numbers)? For instance:
get bits 10:14 from 0x12345678 (signed 0) = 0x15
int getField (int value, int hi, int lo, bool isSigned)
You just have to create a mask:
int createMask(int a, int b){
int c = a;
int mask = 0;
/*First we set the lenght of the mask*/
while(c <= b){ /*Including b*/
mask <<= 1;
mask = mask|1;
c++;
}
/*Then we set the position to the mask, the first bit is in the position 0*/
c=0;
while(c<a){
c++;
mask <<= 1 ;
}
return mask;
}
I haven't tested the function yet, but its just for explaining a way to make a mask.
And the final function may be something like this:
int getBits(int value, int a, int b){
int mask = createMask(a, b);
mask &= value;
//Now we have to move the bits to the right
while(a>0){
mask >>= 1;
a--;
}
return mask;
}
An example, if you want the first 6 bits, you have to code: getBits(myValue, 0, 5).
Im not sure what did you mean about the signeds and unsigneds numbers, but i hope it can help you.
Srry for my english.
I suspect you might want to approach the entire problem in a different way. Rather than extracting bits, why not just use bit masks.
For example, to check if the most significant bit in a byte is enabled:
if(byte & 0xf0) {}
To check for the least significant bit it would be:
if(byte & 0x01) {}
To check for multiple (or a "range") of bits, say the low order nibble:
if(byte & 0x0f) {}
From what you've said, I suspect this is much closer to what you want and much simpler than shifting to extract bits.
That was a bit of fun :) In three easy steps:
shift your value right by the amount lo
and decrease hi
with lo
. This simplifies the problem to 'get the lowest hi bits'.
clip off the highest bits -- a custom mask is created on the fly.
if necessary, use the highest bit to sign-extend the result (bitfiddling based on Sign extending from a constant bit width in C# ).
I don't know the reason for the suggested function prototype, but I would suggest using the order lo, hi
rather than hi, lo
. Somehow 10,14
feels more natural than the other way around, even though bits count down from high to low, when counted left to right -- the computer is supposed to make things easier for us!
#include <stdio.h>
#include <stdbool.h>
int getField (int value, int hi, int lo, bool isSigned)
{
/* step 1: clip off lower bits */
value >>= lo;
hi -= lo-1;
/* step 2: clip off higher bits */
value &= ~(-1<<hi);
/* step 3: extend sign */
if (isSigned && (value & (1<<(hi-1))))
value |= -(1<<hi);
return value;
}
int main (void)
{
int i;
i = getField (0x123456c8, 14,10, true);
printf ("i = %d / %Xh\n", i,i);
return 0;
}
Result:
i = -11 / FFFFFFF5h
which is the correct bit set:
16 12 8 4 0 <- bit position
...4 5 6 7 8 <- value
0100 0101 0110 0111 1000 <- bitwise
--- -- <- mask
101 01 <- result
..111101 01 < sign extended result
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.