Making bitmasks in C - c

I'm new to bit manipulation but I'm struggling to translate it to code.
For the following function I need to make a bitmask
void make_bitmask(unsigned int width, unsigned int shift,unsigned int* mask)
The bitmask function is supposed to have a width and a shift. if w=5 and s=1 it should give 00111110.
How should I approach this? This is my latest code I've been trying:
*mask |= width << shift;
Changed to *mask = ((1 << width) - 1) << shift;
Unit test:
static void test_make_bitmask_correct_width(void)
{
unsigned int mask = 0;
make_bitmask(1,0,&mask)
TEST_ASSERT_EQUAL_HEX32(0x1, mask);
make_bitmask(2,0,&mask)
TEST_ASSERT_EQUAL_HEX32(0x3, mask);
make_bitmask(5,0,&mask)
TEST_ASSERT_EQUAL_HEX32(0x1f, mask);
make_bitmask(32,0,&mask)
TEST_ASSERT_EQUAL_HEX32(0xffffffff, mask); // the one that is currently failing mask is 0x000000000

void make_bitmask(unsigned int width, unsigned int shift,unsigned int *mask)
{
/* With unlimited arithmetic, (1 << width) - 1 would give us a mask of
width bits, starting at the low bit position. E.g., with width 3, 1 <<
3 would give binary 1000, and subtracting one would give 111, a mask of
3 bits. However, in C arithmetic, if width is the full width of an
unsigned int, then "1u << width" would overflow. To avoid this, if
width is positive, we shift 2u by width-1. If width is zero, we simply
use the hardcoded result for a mask of zero bits, zero.
*/
unsigned int t = width ? (2u << width-1) - 1u : 0u;
// Shift the mask to the desired position and store it.
*mask = t << shift;
}

The decimal value 5 is binary 00000101. Shifting it left by one bit gives you 00001010.
If you want 5 to turn into 00011111 (decimal 31) then the easiest solution is to find out the value 00100000 (decimal 32) and the subtracting one.
Remembering that we're dealing with powers of 2, if you raise 2 to the power of 5 we get 32, and can then subtract one to get the base mask. But instead of using the pow function or multiplying in a loop, we can just shift the value 1 five steps left (1 << 5).
Putting it all together, the you should shift 1 left by width bits, subtract 1, and then shift the result shift bits to the left:
*mask = ((1 << width) - 1) << shift;
With width == 5 and shift == 1 then the above will give you binary 00111110 (decimal 62).

Related

How to set masked bits to a specified number?

I haven't been able to find an answer to this on Google, nor do I have any better search ideas. If I have a 2 byte number, a mask, and a third number, how do I replace the masked bits with the third number. For example if I have 0xABCD, the mask 0x0F00, and third number 4 - I would like to replace B with 4 to get A4CD. In other words, I want to be able to replace arbitrary bits selected by a mask with the bits of another arbitrary number (we are assuming that the number replacing the bits fits - i.e. if I mask 5 bits, the number to replace those 5 bits requires 5 bits or less to represent.)
The goal is to replace the bits of number selected by mask with those of value, shifted appropriately, assuming value does not exceed the target range.
Masking off the target bits is easy: number &= ~mask; achieves that simply.
The tricky part is to shift value to the left by the number of zero bits in mask below the set ones. You can write a loop for this.
Here is a simple implementation:
unsigned set_bits(unsigned number, unsigned mask, unsigned value) {
// assuming mask != 0
number &= ~mask;
while (!(mask & 1)) {
value <<= 1;
mask >>= 1;
}
return number | value;
}
You can compute the shift value as a multiplier this way: subtracting one from the mask sets all its 0 low bits to 1, or-ing this value with mask sets all low bits to 1 and xor-ing with mask yields a mask with just the low bits set. Adding 1 to this mask gives the power of 2 by which to multiply value to shift it in place. This works also if there are no 0 bits in the low order bits of mask.
As commented by aschepler, (A ^ (A | B)) == (~A & B) so the expression ((mask ^ (mask | (mask - 1))) + 1) can be simplified as (((mask - 1) & ~mask) + 1).
An elegant simplification was provided by Falk Hüffner: (((mask - 1) & ~mask) + 1) is just mask & -mask.
Here is a branchless version using this trick:
unsigned set_bits(unsigned number, unsigned mask, unsigned value) {
return (number & ~mask) | (value * (mask & -mask));
}
Making this an inline function may help the compiler generate optimal code for constant mask values.

Can anyone explain this bitwise function to compute log(n)

int howManyBits(int x) {
int concatenate;
int bias;
int sign = x >> 31; //get the sign
x = (sign & (~x)) | (~sign & x);
concatenate = (!!(x >> 16)) << 4;
concatenate |= (!!(x >> (concatenate + 8))) << 3;
concatenate |= (!!(x >> (concatenate + 4))) << 2;
concatenate |= (!!(x >> (concatenate + 2))) << 1;
concatenate |= x >> (concatenate + 1);
bias = !(x ^ 0);
return concatenate + 2 + (~bias + 1);
}
This code is presented as a way to calculate the minimum number of bits required to represent an integer n in 2's complement, with the assumption that the int data type is represented with 32 bits. Right shifting is assumed to be arithmetic.
I understand that the basic method is to take the log base 2 of n, round it up, and then add 1 bit to account for the sign bit.
I also understand that left-shifting is equivalent to multiplying by 2 and that right-shifting is equivalent to dividing by 2.
That being said, without comments I can't decipher what this code is doing beyond the portion where it obtains the value of the sign bit. I worked through it on pencil and paper with a sample int of the value 5 - the code works, but I don't understand why.
Could someone provide some intuitive breakdown of what the code is doing?
This code could use some comments.
This leaves x as it is if it is positive or takes the one's complement if negative. This allows the calculation to search for the most significant one regardless of positive or negative
x = (sign & (~x)) | (~sign & x);
I think the following would have been more clear:
x = sign ? ~x : x;
Next is a search for the highest 1 bit done with a binary search. First the top half of the word is searched.
concatenate = (!!(x >> 16)) << 4;
If the top half has a 1, then the result is 16. The 16 is used later both as part of the answer, but also to determine where to search next. Since it is used in the shifts that follow it will cause the following tests to either be done with the top half of the board or the bottom half.
The following concatenate operations are searching in a progressively smaller piece of the original number looking is the most significant one in the upper 8 bits or the lower 8 bits of the 16 bits that was chosen, then the upper 4 bits or the lower 4 bits of the 8 bits that was chosen, and so forth.
concatenate |= (!!(x >> (concatenate + 8))) << 3; // Check which 8 bits
concatenate |= (!!(x >> (concatenate + 4))) << 2; // Check which 4 bits
concatenate |= (!!(x >> (concatenate + 2))) << 1; // Check which 2 bits
concatenate |= x >> (concatenate + 1); // Check which 1 bit
The bias is just checking is the number 0 or not. It is 1 only if x is 0. I don't understand the need for the XOR operator.
Finally the pieces are added together.

How do I extract bits from 32 bit number

I have do not have much knowledge of C and I'm stuck with a problem since one of my colleague is on leave.
I have a 32 bit number and i have to extract bits from it. I did go through a few threads but I'm still not clear how to do so. I would be highly obliged if someone can help me.
Here is an example of what I need to do:
Assume hex number = 0xD7448EAB.
In binary = 1101 0111 0100 0100 1000 1110 1010 1011.
I need to extract the 16 bits, and output that value. I want bits 10 through 25.
The lower 10 bits (Decimal) are ignored. i.e., 10 1010 1011 are ignored.
And the upper 6 bits (Overflow) are ignored. i.e. 1101 01 are ignored.
The remaining 16 bits of data needs to be the output which is 11 0100 0100 1000 11 (numbers in italics are needed as the output).
This was an example but I will keep getting different hex numbers all the time and I need to extract the same bits as I explained.
How do I solve this?
Thank you.
For this example you would output 1101 0001 0010 0011, which is 0xD123, or 53,539 decimal.
You need masks to get the bits you want. Masks are numbers that you can use to sift through bits in the manner you want (keep bits, delete/clear bits, modify numbers etc). What you need to know are the AND, OR, XOR, NOT, and shifting operations. For what you need, you'll only need a couple.
You know shifting: x << y moves bits from x *y positions to the left*.
How to get x bits set to 1 in order: (1 << x) - 1
How to get x bits set to 1, in order, starting from y to y + x: ((1 << x) -1) << y
The above is your mask for the bits you need. So for example if you want 16 bits of 0xD7448EAB, from 10 to 25, you'll need the above, for x = 16 and y = 10.
And now to get the bits you want, just AND your number 0xD7448EAB with the mask above and you'll get the masked 0xD7448EAB with only the bits you want. Later, if you want to go through each one, you'll need to shift your result by 10 to the right and process each bit at a time (at position 0).
The answer may be a bit longer, but it's better design than just hard coding with 0xff or whatever.
OK, here's how I wrote it:
#include <stdint.h>
#include <stdio.h>
main() {
uint32_t in = 0xd7448eab;
uint16_t out = 0;
out = in >> 10; // Shift right 10 bits
out &= 0xffff; // Only lower 16 bits
printf("%x\n",out);
}
The in >> 10 shifts the number right 10 bits; the & 0xffff discards all bits except the lower 16 bits.
I want bits 10 through 25.
You can do this:
unsigned int number = 0xD7448EAB;
unsigned int value = (number & 0x3FFFC00) >> 10;
Or this:
unsigned int number = 0xD7448EAB;
unsigned int value = (number >> 10) & 0xFFFF;
I combined the top 2 answers above to write a C program that extracts the bits for any range of bits (not just 10 through 25) of a 32-bit unsigned int. The way the function works is that it returns bits lo to hi (inclusive) of num.
#include <stdio.h>
#include <stdint.h>
unsigned extract(unsigned num, unsigned hi, unsigned lo) {
uint32_t range = (hi - lo + 1); //number of bits to be extracted
//shifting a number by the number of bits it has produces inconsistent
//results across machines so we need a special case for extract(num, 31, 0)
if(range == 32)
return num;
uint32_t result = 0;
//following the rule above, ((1 << x) - 1) << y) makes the mask:
uint32_t mask = ((1 << range) -1) << lo;
//AND num and mask to get only the bits in our range
result = num & mask;
result = result >> lo; //gets rid of trailing 0s
return result;
}
int main() {
unsigned int num = 0xd7448eab;
printf("0x%x\n", extract(num, 10, 25));
}

Introducing errors by flipping bits

I have a character array in C into which I want to introduce errors by flipping some bits.
How can I flip bits and introduce errors?
You can flip bits using the xor operator:
x = x ^ mask;
x ^= mask; // Same functionality as above.
For example, if mask is 1, the least significant bit is flipped. You can create any desired mask by bit-shifting the 1: mask = 1 << k; where k is the number of bits to shift.
For distributing the errors, use a random number generator. rand() / srand() should suffice if this is for test purposes.
To flip a bit you can use the bit shifting and bitwise xor operators.
unsigned char flip(unsigned char c, int bit) {
return c ^ (1 << bit);
}
You can also flip more than one bit by using a bitmask other than (1 << bit), which has just one bit set:
unsigned char flip(unsigned char c, unsigned char mask) {
return c ^ (1 << mask);
}
// flip bits 0 and 3 (00001001 = 0x09)
flip(c, 0x09);

How can I access a specific group of bits from a variable?

I have a variable with "x" number of bits. How can I extract a specific group of bits and then work on them in C?
You would do this with a series of 2 bitwise logical operations.
[[Terminology MSB (msb) is the most-significant-bit; LSB (lsb) is the least-significant-bit. Assume bits are numbered from lsb==0 to some msb (e.g. 31 on a 32-bit machine). The value of the bit position i represents the coefficient of the 2^i component of the integer.]]
For example if you have int x, and you want to extract some range of bits x[msb..lsb] inclusive, for example a 4-bit field x[7..4] out of the x[31..0] bits, then:
By shifting x right by lsb bits, e.g. x >> lsb, you put the lsb bit of x in the 0th (least significant) bit of the expression, which is where it needs to be.
Now you have to mask off any remaining bits above those designated by msb. The number of such bits is msb-lsb + 1. We can form a bit mask string of '1' bits that long with the expression ~(~0 << (msb-lsb+1)). For example ~(~0 << (7-4+1)) == ~0b11111111111111111111111111110000 == 0b1111.
Putting it all together, you can extract the bit vector you want with into a new integer with this expression:
(x >> lsb) & ~(~0 << (msb-lsb+1))
For example,
int x = 0x89ABCDEF;
int msb = 7;
int lsb = 4;
int result = (x >> lsb) & ~(~0 << (msb-lsb+1));
// == 0x89ABCDE & 0xF
// == 0xE (which is x[7..4])
Make sense?
Happy hacking!
If you're dealing with a primitive then just use bitwise operations:
int bits = 0x0030;
bool third_bit = bits & 0x0004; // bits & 00000100
bool fifth_bit = bits & 0x0010; // bits & 00010000
If x can be larger than a trivial primitive but is known at compile-time then you can use std::bitset<> for the task:
#include<bitset>
#include<string>
// ...
std::bitset<512> b(std::string("001"));
b.set(2, true);
std::cout << b[1] << ' ' << b[2] << '\n';
std::bitset<32> bul(0x0010ul);
If x is not known at compile-time then you can use std::vector<unsigned char> and then use bit-manipulation at runtime. It's more work, the intent reads less obvious than with std::bitset and it's slower, but that's arguably your best option for x varying at runtime.
#include<vector>
// ...
std::vector<unsigned char> v(256);
v[2] = 1;
bool eighteenth_bit = v[2] & 0x02; // second bit of third byte
work on bits with &, |. <<, >> operators.
For example, if you have a value of 7 (integer) and you want to zero out the 2nd bit:
7 is 111
(zero-ing 2nd bit AND it with 101 (5 in decimal))
111 & 101 = 101 (5)
here's the code:
#include <stdio.h>
main ()
{
int x=7;
x= x&5;
printf("x: %d",x);
}
You can do with other operators like the OR, shift left, shift right,etc.
You can use bitfields in a union:
typedef union {
unsigned char value;
struct { unsigned b0:1,b1:1,b2:1,b3:1,b4:1,b5:1,b6:1,b7:1; } b;
struct { unsigned b0:2,b1:2,b2:2,b3:2; } b2;
struct { unsigned b0:4,b1:4; } b4;
} CharBits;
CharBits b={0},a={0};
printf("\n%d",b.value);
b.b.b0=1; printf("\n%d",b.value);
b.b.b1=1; printf("\n%d",b.value);
printf("\n%d",a.value);
a.b4.b1=15; printf("\n%d",a.value); /* <- set the highest 4-bit-group with one statement */

Resources