Related
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...
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).
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 */
}
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
}
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;
}
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
}
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
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;
Let's take int as an example:
int SetBitWithinRange(const unsigned from, const unsigned to)
{
//To be implemented
}
SetBitWithinRange is supposed to return an intin which all and only the bits starting at bit from to bit to are set, when from is smaller than to and both are in the range of 0 to 32.
e.g.:
int i = SetBitWithinRange(2,4) will result in i having the value of 0b00...01100
Here are some ways. First, some variants of "set n bits, then shift by from". I'll answer in C# though, I'm more familiar with it than I am with C. Should be easy to convert.
uint nbits = 0xFFFFFFFFu >> -(to - from);
return nbits << from;
Downside: can't handle an empty range, ie the case where to <= from.
uint nbits = ~(0xFFFFFFFFu << (to - from));
return nbits << from;
Upside: can handle the case where to = from in which case it will set no bits.
Downside: can't handle the full range, ie setting all bits.
It should be obvious how these work.
Alternatively, you can use the "subtract two powers of two" trick,
(1u << to) - (1u << from)
Downside: to can not be 32, so you can never set the top bit.
Works like this:
01000000
^^^^^^ "to" zeroes
100
^^ "from zeroes"
-------- -
00111100
To the right of the 1 in the "from" part, it's just zeroes being subtracted from zeroes. Then at the 1 in the "from" part, you will either subtract from a 1 (if to == from) and get 0 as a result, or you'll subtract a 1 from a 0 and borrow all the way to the 1 in the to part, which will be reset.
All true bitwise methods that have been proposed at the time of writing have one of those downsides, which raises the question: can it be done without downsides?
The answer is, unfortunately, disappointing. It can be done without downsides, but only by
cheating (ie using non-bitwise elements), or
more operations than would be nice, or
non-standard operations
To give an example of 1, you can just pick any of the previous methods and add a special case (with an if or ternary operator) to work around their downside.
To give an example of 2: (not tested)
uint uppermask = (((uint)to >> 5) ^ 1) << to;
return uppermask - (1u << from);
The uppermask either takes a 1 and shifts it left by to (as usual), or it takes a 0 and shifts it left (by an amount that doesn't matter, since it's 0 that's being shifted), if to == 32. But it's kind of weird and uses more operations.
To give an example of 3, shifts that give zero when you shift by the operand size or more would solve this very easily. Unfortunately, that kind of shift isn't too common.
A common way to do this somewhat efficiently would be this:
uint32_t set_bits_32 (uint32_t data, uint8_t offset, uint8_t n)
{
uint32_t mask = 0xFFFFFFFF >> (32-n);
return data | (mask << offset);
}
I'd go with something like that:
int answer = 0;
unsigned i = from;
for (; i <= to; ++i)
answer |= (1 << i);
return answer;
Easy to implement & readable.
I think that the fastest way would be to pre-calculate all possible values (from (0, 0) to (32, 32), if you know that you'll use this only for 32-bit integers). In fact there are about 1000 of them.
Then you'll end up with O(1) solution:
answer = precalcTable[from][to];
OK, I'm taking up the gauntlet that #JohnZwinck has thrown towards me.
How about:
return (to<32 ? (1<<to) : 0) - (1<<from);
Of course this is without fully checking for validity of from and to.
Edited according to #JosephQuinsey comments.
maybe: (( 1 << to ) - (1 << from)) | (1 << to)
This will also set the to and from bits as requested
Here's my answer. (updated)
unsigned int SetBits(int from, int to)
{
return (UINT_MAX >> (CHAR_BIT*sizeof(int)-to)) & (UINT_MAX << (from-1));
}
SetBits(9,16); ==> 0b 1111 1111 0000 0000
SetBits(1,1); ==> 0b 0000 0001 // Just Bit #1
SetBits(5,5); ==> 0b 0001 0000 // Just Bit #5
SetBits(1,4); ==> 0b 0000 1111 // Bits #1, #2, #3, and #4 (low 4 bits)
SetBits(1,32); ==> 0b 1111 1111 1111 1111 // All Bits
However, SetBits(0,0); does NOT work for turning all bits off.
My assumptions:
Bits are 1-based, starting from the right.
Bytes are 8-bits.
Ints can be any size (16, 32 or 64 bit). sizeof(int) is used.
No checking is done on from or to; caller must pass proper values.
Can be done in this way as well, pow can be implemented using shift operations.
{
unsigned int i =0;
i = pow(2, (to-from))-1;
i = i <<from;
return i;
}
I have a method that computes a hash value as per some specific algorithm.
uint8_t cal_hash(uint64_t _in_data) {
uint8_t hash;
// algorithm
// bit at hash[0] = XOR of some specific bits in _in_data
// repeat above statement for other indexed bits of hash
return hash;
}
I want to know what could be the most efficient way to access and set corresponding bits in an integer datatype.
I have already tried things like
(((x) & (1<<(n)))?1:0)
to determine if a bit is 1 or 0 at any index. Anything better than this ?
I think this is a speed vs. memory type question. (Updated with MrSmith42s suggestion):
If you really want speed I would define a mask for each bit a compare that. Perhaps something like:
const uint8_t BitMask[] = { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 };
/* Find out if LSB is set */
if( hash & BitMask[0] ) { ... }
The problem with shifts is that it uses an instruction per shift whereas a fixed mask will only have a single memory acces before the comparison.
Your first concern should be to have a correct and portable version. Compilers nowadays will then optimize such bit operations quite cleverly.
You should always take care that the mask you are using corresponds to the data type that you are testing. Using an int or unsigned might not be enough since you are interested in the bits of a uint64_t and shifting for more than there are bits is undefined behavior.
In your case you would probably use something like
(UINT64_C(1) << (n))
for the mask. If you want to do this in a more generic way you'd have to obtain a 1 of your base type by something like
(1 ? 1U : (X))
alltogether in a macro
#define MASK(X, N) ((1 ? 1U : (X)) << (N))
and then the test could look like
#define BIT(X, N) !!((X) & MASK(X, N))
For finding a bit that is set quickly, try this:
int oneBit = x & ~(x-1);
After this, oneBit will have ONLY the lowest bit of X set.
(eg, if x was 1011 0100, oneBit will be 0000 0100, eg. just the lowest bit)
After that, you can turn off the lowest bit with:
x &= x-1;
(eg: if x was 1011 0100, new x should be 1011 0000)
Then you can repeat the first operation to find the next lowest bit that was set.
This has the great advantage that you don't spend time "testing" a bit only to find out that its zero.It gets you directly to those bits that are set, and skips bits that are zero.
Here's example code that shows it in action:
int main(void)
{
int x = 180; // 1011 0100
while (x)
{
printf("Low Bit is: %d\n", x & ~(x-1));
x &= (x-1);
}
}
Output:
Low Bit is: 4 // eg. 0000 0100
Low Bit is: 16 // eg. 0001 0000
Low Bit is: 32 // eg. 0010 0000
Low Bit is: 128 // eg. 1000 0000
I'm looking at a datasheet specification of a NIC and it says:
bits 2:3 of register contain the NIC speed, 4 contains link state, etc. How can I isolate these bits using bitwise?
For example, I've seen the code to isolate the link state which is something like:
(link_reg & (1 << 4))>>4
But I don't quite get why the right shift. I must say, I'm still not fairly comfortable with the bitwise ops, even though I understand how to convert to binary and what each operation does, but it doesn't ring as practical.
It depends on what you want to do with that bit. The link state, call it L is in a variable/register somewhere
43210
xxxxLxxxx
To isolate that bit you want to and it with a 1, a bitwise operation:
xxLxxxx
& 0010000
=========
00L0000
1<<4 = 1 with 4 zeros or 0b10000, the number you want to and with.
status&(1<<4)
This will give a result of either zero or 0b10000. You can do a boolean comparison to determine if it is false (zero) or true (not zero)
if(status&(1<<4))
{
//bit was on/one
}
else
{
//bit was off/zero
}
If you want to have the result be a 1 or zero, you need to shift the result to the ones column
(0b00L0000 >> 4) = 0b0000L
If the result of the and was zero then shifting still gives zero, if the result was 0b10000 then the shift right of 4 gives a 0b00001
so
(status&(1<<4))>>4 gives either a 1 or 0;
(xxxxLxxxx & (00001<<4))>>4 =
(xxxxLxxxx & (10000))>>4 =
(0000L0000) >> 4 =
0000L
Another way to do this using fewer operations is
(status>>4)&1;
xxxxLxxxx >> 4 = xxxxxxL
xxxxxxL & 00001 = 00000L
Easiest to look at some binary numbers.
Here's a possible register value, with the bit index underneath:
00111010
76543210
So, bit 4 is 1. How do we get just that bit? We construct a mask containing only that bit (which we can do by shifting a 1 into the right place, i.e. 1<<4), and use &:
00111010
& 00010000
----------
00010000
But we want a 0 or a 1. So, one way is to shift the result down: 00010000 >> 4 == 1. Another alternative is !!val, which turns 0 into 0 and nonzero into 1 (note that this only works for single bits, not a two-bit value like the link speed).
Now, if you want bits 3:2, you can use a mask with both of those bits set. You can write 3 << 2 to get 00001100 (since 3 has two bits set). Then we & with it:
00111010
& 00001100
----------
00001000
and shift down by 2 to get 10, the desired two bits. So, the statement to get the two-bit link speed would be (link_reg & (3<<2))>>2.
If you want to treat bits 2 and 3 (starting the count at 0) as a number, you can do this:
unsigned int n = (link_get & 0xF) >> 2;
The bitwise and with 15 (which is 0b1111 in binary) sets all but the bottom four bits to zero, and the following right-shift by 2 gets you the number in bits 2 and 3.
you can use this to determine if the bit at position pos is set in val:
#define CHECK_BIT(val, pos) ((val) & (1U<<(pos)))
if (CHECK_BIT(reg, 4)) {
/* bit 4 is set */
}
the bitwise and operator (&) sets each bit in the result to 1 if both operands have the corresponding bit set to 1. otherwise, the result bit is 0.
The problem is that isolating bits is not enough: you need to shift them to get the correct size order of the value.
In your example you have bit 2 and 3 for the size (I'm assuming that least significant is bit 0), it means that it is a value in range [0,3]. Now you can mask these bits with reg & (0x03<<2) or, converted, (reg & 0x12) but this is not enough:
reg 0110 1010 &
0x12 0000 1100
---------------
0x08 0000 1000
As you can see the result is 1000b which is 8, which is over the range. To solve this you need to shift back the result so that the least significant bit of the value you are interested in corresponds to the least significant bit of the containing byte:
0000 1000 >> 2 = 10b = 3
which now is correct.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Find the highest order bit in C
How can I write a C function that will generate a mask indicating the leftmost 1 in x.
Ex: 0xFF00 -> 0x8000, and 0x6600 -> 0x4000. So far:
int left1(unsigned x){}
I understand, 0xFF00 == 1111 1111 0000 0000..
and 0x6600 == 0110 0110 0000 0000.. but I'm stumped after that.
You can do this in two parts: first, use a technique called "bit smearing" to ensure that all the bits to the right of the first 1 are also 1:
x |= x >> 16;
x |= x >> 8;
x |= x >> 4;
x |= x >> 2;
x |= x >> 1;
At this point, an input of 0xFF00 will leave x equal to 0xFFFF, and an input of 0x6600 will leave x equal to 0x7FFF. We can then leave just the highest 1 set using:
x ^= x >> 1;
Count the number of times it takes to bit-shift to the right until you reach 1, then bit-shift that 1 to the left by that same count.
int ct=0;
while (x > 1) { ct++; x = x >> 1; }
x = x << ct;
One approach is to create a bitmask, and then right-shift the value.
That is, create a bitmask so that your integer is '1000....' or '0.....' - depending on whether that first bit is a 0 or a 1.
Then take that integer and right-shift it until it becomes the least-significant-bit, rather than the most-significant. As an example, 0b10000000 >> 8 is 1.
So first, depending on the size of your integer, you have to shift, well, however many bits are relevant.
Then you have to create the bitmask. Let's just take a 1-byte integer:
unsigned int i = 1 << 8 would create an integer i whose most significant bit is a 1.
Or you could use hex. You already know that 0xFF == 11111111. You can actually break it up further: 0xF0 == 11110000
Since 0xF == 1111 in binary, well, we will do the reverse. 1000 in binary is what, in hex? 1000 in binary is the number 8, which also happens to equal 0x8
So, for a single byte, the mask for the leftmost bit is 0x80.
Now! Apply this to 32 bits!
Good luck!