What is the best way to construct a bit mask in C with m
set bits preceded by k
unset bits, and followed by n
unset bits:
00..0 11..1 00..0
k m n
For example, k=1, m=4, n=3 would result in the bit mask:
01111000
What is the best way to construct a bit mask in C with m
set bits preceded by k
unset bits, and followed by n
unset bits:
00..0 11..1 00..0
k m n
For example, k=1, m=4, n=3 would result in the bit mask:
01111000
So, you are asking for m set bits prefixed by k reset bits and followed by n reset bits? We can ignore k since it will largely be constrained by the choice of integer type.
mask = ((1 << m) - 1) << n;
I like both solutions. Here is another way that comes to my mind (probably not better).
((~((unsigned int)0) << k) >> (k + n)) << n
EDIT:
There was a bug in my previous version (it was without the unsigned int cast). The problem was that ~0 >> n
adds 1s at the front and not 0s.
And yes this approach has one big downside; it assumes that you know the number of bits of the default integer type or in other words it assumes that you really know k, whereas the other solutions are independent of k. This makes my version less portable, or at least harder to port. (It also uses 3 shifts, and addition and a bitwise negation operator, which is two extra operations.)
So you would do better to use one of the other examples.
Here is a little test app, done by Jonathan Leffler, to compare and verify the output of the different solutions:
#include <stdio.h>
#include <limits.h>
enum { ULONG_BITS = (sizeof(unsigned long) * CHAR_BIT) };
static unsigned long set_mask_1(int k, int m, int n)
{
return ~(~0 << m) << n;
}
static unsigned long set_mask_2(int k, int m, int n)
{
return ((1 << m) - 1) << n;
}
static unsigned long set_mask_3(int k, int m, int n)
{
return ((~((unsigned long)0) << k) >> (k + n)) << n;
}
static int test_cases[][2] =
{
{ 1, 0 },
{ 1, 1 },
{ 1, 2 },
{ 1, 3 },
{ 2, 1 },
{ 2, 2 },
{ 2, 3 },
{ 3, 4 },
{ 3, 5 },
};
int main(void)
{
size_t i;
for (i = 0; i < 9; i++)
{
int m = test_cases[i][0];
int n = test_cases[i][1];
int k = ULONG_BITS - (m + n);
printf("%d/%d/%d = 0x%08lX = 0x%08lX = 0x%08lX\n", k, m, n,
set_mask_1(k, m, n),
set_mask_2(k, m, n),
set_mask_3(k, m, n));
}
return 0;
}