66

I was facing this unique problem of generating a bit-mask based on the input parameter. For example,

if param = 2, then the mask will be 0x3 (11b) if param = 5, then the mask will be 0x1F (1 1111b)

This I implemented using a for-loop in C, something like

int nMask = 0;
for (int i = 0; i < param; i ++) {

    nMask |= (1 << i);
}

I would like to know if there is a better algorithm ~~~

phuclv
  • 37,963
  • 15
  • 156
  • 475
Alphaneo
  • 12,079
  • 22
  • 71
  • 89
  • Going by your description, this would probably be the simplest you could do.. pending any inbuilt stuff :p – glasnt Sep 08 '09 at 05:01
  • Related: *[How to replace bits in a bitfield without affecting other bits using C](https://stackoverflow.com/questions/5925755/how-to-replace-bits-in-a-bitfield-without-affecting-other-bits-using-c)* and *[How do you set only certain bits of a byte in C without affecting the rest?](https://stackoverflow.com/questions/4439078/how-do-you-set-only-certain-bits-of-a-byte-in-c-without-affecting-the-rest)* – Peter Mortensen Aug 14 '23 at 14:51

9 Answers9

117

One thing to notice about bitmasks like that is that they are always one less than a power of two.

The expression 1 << n is the easiest way to get the n-th power of two.

You don't want Zero to provide a bitmask of 00000001, you want it to provide zero. So you need to subtract one.

mask = (1 << param) - 1;

Edit:

If you want a special case for param > 32:

int sizeInBits = sizeof(mask) * BITS_PER_BYTE; // BITS_PER_BYTE = 8;
mask = (param >= sizeInBits ? -1 : (1 <<  param) - 1);

This method should work for 16, 32, or 64 bit integers, but you may have to explicitly type the '1'.

roschach
  • 8,390
  • 14
  • 74
  • 124
John Gietzen
  • 48,783
  • 32
  • 145
  • 190
  • 6
    Nice idea, subtracting to get all ones :) – Khaled Alshaya Sep 08 '09 at 05:06
  • Thanks. I figured it out when I was building binary trees for a single elimination bracket. – John Gietzen Sep 08 '09 at 05:07
  • 11
    This is the canonical solution, with two caveats. First, you should probably be using `unsigned int` for `mask` and `1U` as the left side of the shift operator, and secondly be aware that the result is unspecified if `param` is equal or greater than the number of bits in `int` (or one less than the number of bits, if you continue to use signed math). If this is a problem in your environment, use a lookup table instead. – caf Sep 08 '09 at 05:33
  • @caf: Good points, but a lookup table won't fix things if there aren't enough bits in your environment's unsigned type! – j_random_hacker Sep 08 '09 at 13:19
  • A lookup table will work for the case of param *equal* to the number of bits in `unsigned int` (the "all ones" case), though. – caf Sep 09 '09 at 00:27
  • Right. Will the memory look-up be faster than the bit-wise arithmetic and subtraction? – John Gietzen Sep 09 '09 at 03:42
  • @caf: True, but since that's the only case where the lookup table would be an improvement, I'd probably just special-case it with an `if (param == sizeof (unsigned) * CHAR_BIT) { mask = (unsigned) -1; }` instead, which is guaranteed (in C++ at least) to give you all-bits-on. – j_random_hacker Sep 09 '09 at 04:13
  • 1
    Also, while the C++ standard strictly says that the case `param == width_of_unsigned_in_bits` produces Undefined Behaviour for left-shift, it would be very surprising to meet an implementation that did not just produce the value 0 in this case. So in practice I wouldn't actually bother with the special case `if`, since the mainline code handles it fine. – j_random_hacker Sep 09 '09 at 04:17
  • The reason it says it is undefined is because it is usually translated directly a processor op, and there can be no guarantees made on all processors. I expect at least one processor somewhere produces a different result for left shift. But on x86 and compatible processors, I think you can be safe to say that the main line code will work. – John Gietzen Sep 09 '09 at 13:15
  • 3
    Have you actually tested it? On my x86, under gcc, it produces zero as the mask for `param = 32`, not all-ones (because the x86 shift actually shifts by param modulo 32). I don't think the lookup table would be significantly slower in most cases. – caf Sep 10 '09 at 02:02
  • Ah!, didn't realize that. No I had not tested it. – John Gietzen Sep 10 '09 at 13:06
  • @caf: Interesting! Same behaviour on MSVC++9 on x86. I stand corrected. My instinct is still to go with the special-case `if` test, but a lookup table should be roughly as fast. – j_random_hacker Sep 10 '09 at 20:08
  • I just broke my head thinking how to bitwise left-shift getting all 1's, nice idea substracting one – Edher Carbajal Mar 02 '21 at 08:24
  • I expect this won't work for `param >= 32`. You would need to use `(1ULL << param) - 1` to get the correct result. – Touloudou Oct 09 '21 at 08:18
  • I like the idea of checking for the size of the int holding the mask. However, if that size is constant and known, what I have done is: `(size_t) 1 << (2*K-1) | ((size_t) 1 << (2*K-1)) - 1`. It isn't super pretty, but it avoids a ternary operator. Probably not the best option, but I wanted to throw it in the mix nonetheless! – AugustoQ Mar 04 '22 at 01:11
30

Efficient, Branch-Free, Portable and Generic (but Ugly) Implementation

C:

#include <limits.h>     /* CHAR_BIT */

#define BIT_MASK(__TYPE__, __ONE_COUNT__) \
    ((__TYPE__) (-((__ONE_COUNT__) != 0))) \
    & (((__TYPE__) -1) >> ((sizeof(__TYPE__) * CHAR_BIT) - (__ONE_COUNT__)))

C++:

#include <climits>

template <typename R>
static constexpr R bitmask(unsigned int const onecount)
{
//  return (onecount != 0)
//      ? (static_cast<R>(-1) >> ((sizeof(R) * CHAR_BIT) - onecount))
//      : 0;
    return static_cast<R>(-(onecount != 0))
        & (static_cast<R>(-1) >> ((sizeof(R) * CHAR_BIT) - onecount));
}

Usage (Producing Compile Time Constants)

BIT_MASK(unsigned int, 4) /* = 0x0000000f */

BIT_MASK(uint64_t, 26) /* = 0x0000000003ffffffULL */

Example

#include <stdio.h>

int main()
{
    unsigned int param;
    for (param = 0; param <= 32; ++param)
    {
        printf("%u => 0x%08x\n", param, BIT_MASK(unsigned int, param));
    }
    return 0;
}

Output

0 => 0x00000000
1 => 0x00000001
2 => 0x00000003
3 => 0x00000007
4 => 0x0000000f
5 => 0x0000001f
6 => 0x0000003f
7 => 0x0000007f
8 => 0x000000ff
9 => 0x000001ff
10 => 0x000003ff
11 => 0x000007ff
12 => 0x00000fff
13 => 0x00001fff
14 => 0x00003fff
15 => 0x00007fff
16 => 0x0000ffff
17 => 0x0001ffff
18 => 0x0003ffff
19 => 0x0007ffff
20 => 0x000fffff
21 => 0x001fffff
22 => 0x003fffff
23 => 0x007fffff
24 => 0x00ffffff
25 => 0x01ffffff
26 => 0x03ffffff
27 => 0x07ffffff
28 => 0x0fffffff
29 => 0x1fffffff
30 => 0x3fffffff
31 => 0x7fffffff
32 => 0xffffffff

Explanation

First of all, as already discussed in other answers, >> is used instead of << in order to prevent the problem when the shift count is equal to the number of bits of the storage type of the value. (Thanks Julien's answer above for the idea)

For the ease of discussion, let's "instantiate" the macro with unsigned int as __TYPE__ and see what happens (assuming 32-bit for the moment):

((unsigned int) (-((__ONE_COUNT__) != 0))) \
& (((unsigned int) -1) >> ((sizeof(unsigned int) * CHAR_BIT) - (__ONE_COUNT__)))

Let's focus on:

((sizeof(unsigned int) * CHAR_BIT)

first. sizeof(unsigned int) is known at compile time. It is equal to 4 according to our assumption. CHAR_BIT represents the number of bits per char, a.k.a. per byte. It is also known at compile time. It is equal to 8 on most machines on the Earth. Since this expression is known at a compile time, the compiler would probably do the multiplication at compile time and treat it as a constant, which equals to 32 in this case.

Let's move to:

((unsigned int) -1)

It is equal to 0xFFFFFFFF. Casting -1 to any unsigned type produces a value of "all-1s" in that type. This part is also a compile time constant.

Up to now, the expression:

(((unsigned int) -1) >> ((sizeof(unsigned int) * CHAR_BIT) - (__ONE_COUNT__)))

is in fact the same as:

0xffffffffUL >> (32 - param)

which is the same as Julien's answer above. One problem with his answer is that if param is equal to 0, producing the expression 0xffffffffUL >> 32, the result of the expression would be 0xffffffffUL, instead of the expected 0! (That's why I name my parameter as __ONE_COUNT__ to emphasize its intention)

To solve this problem, we could simply add a special case for __ONE_COUNT equals 0 using if-else or ?:, like this:

#define BIT_MASK(__TYPE__, __ONE_COUNT__) \
    (((__ONE_COUNT__) != 0) \
    ? (((__TYPE__) -1) >> ((sizeof(__TYPE__) * CHAR_BIT) - (__ONE_COUNT__)))
    : 0)

But branch-free code is cooler, isn't it?! Let's move to the next part:

((unsigned int) (-((__ONE_COUNT__) != 0)))

Let's start from the innermost expression to the outermost. ((__ONE_COUNT__) != 0) produces 0 when the parameter is 0, or 1 otherwise. (-((__ONE_COUNT__) != 0)) produces 0 when the parameter is 0, or -1 otherwise. For ((unsigned int) (-((__ONE_COUNT__) != 0))), the type-cast trick ((unsigned int) -1) is already explained above. Do you notice the trick now? The expression:

((__TYPE__) (-((__ONE_COUNT__) != 0)))

equals to "all-0s" if __ONE_COUNT__ is zero, and "all-1s" otherwise. It acts as a bit-mask for the value we calculated in the first step. So, if __ONE_COUNT__ is non-zero, the mask as no effect and it is the same as Julien's answer. If __ONE_COUNT__ is 0, it mask away all bits of Julien's answer, producing a constant zero. To visualize, watch this:

__ONE_COUNT__ :                           0                Other
                                          -------------    --------------
(__ONE_COUNT__)                           0 = 0x000...0    (itself)
((__ONE_COUNT__) != 0)                    0 = 0x000...0     1 = 0x000...1
((__TYPE__) (-((__ONE_COUNT__) != 0)))    0 = 0x000...0    -1 = 0xFFF...F
Community
  • 1
  • 1
  • 3
    While this is a great answer, the macro as written it invokes undefined behaviour due to using reserved identifiers. – Remember Monica Jul 18 '18 at 16:20
  • 4
    Actually, it's worse, it also invokes undefined behaviour in the shift (shifting a 32 bit unsigned right by 32 invokes undefined behaviour), so this doesn't even solve the problem after fixing the identifier problem, as it could crash or delete your files. – Remember Monica Jul 18 '18 at 16:27
  • As an additional note, most simple uses of the tertiary operator arebranch free on modern cpus, while the "branch free" version isn't guaranteed to be branch free at all. – Remember Monica Jul 18 '18 at 16:28
  • @MarcLehmann : What is the reserved identifier you are talking about? Thanks! – Siu Ching Pong -Asuka Kenji- Jul 18 '18 at 17:08
  • 1
    @MarcLehmann : Can you give me an example on how shifting right 32 bit would trigger a file to be deleted? Which platform and which compiler would do so? I don't think any current or future compiler would have such insane behavior. While you say that the behavior is undefined, would you please quote the origin of your claim, like which specification or which article says that? – Siu Ching Pong -Asuka Kenji- Jul 18 '18 at 17:13
  • 2
    @SiuChingPong-AsukaKenji- An example would be that it triggers a CPU exception that causes the runtime to jump to a function that deletes files which could then interpret whatever registers are set to delete some files. It's true that this might not happen on your specific compiler and/or platform, but the question was about the C language, not a specific implementation of it. As for the origin of the claim, see any version of the C standard and search for "undefined behaviour". – Remember Monica Jul 22 '18 at 23:40
  • 1
    @SiuChingPong-AsukaKenji- Identifiers that start with double underscores are always reserved. In your case, \_\_ONE_COUNT\_\_ and \_\_TYPE\_\_. Again, using these identifiers triggers undefined behaviour, which could result in deleted files or worse := – Remember Monica Jul 22 '18 at 23:42
  • @SiuChingPong-AsukaKenji- as for where the specific behaviour of shift operators is defined, again, just refer to any version of the C standard which explains the valid ranges for shift operations quite nicely. – Remember Monica Jul 22 '18 at 23:44
13

Alternatively, you can use a right shift to avoid the issue mentioned in the (1 << param) - 1 solution.

unsigned long const mask = 0xffffffffUL >> (32 - param);

assuming that param <= 32, of course.

Julien Royer
  • 1,419
  • 1
  • 14
  • 27
8

For those interested, this is the lookup-table alternative discussed in comments to the other answer - the difference being that it works correctly for a param of 32. It's easy enough to extend to the 64 bit unsigned long long version, if you need that, and shouldn't be significantly different in speed (if it's called in a tight inner loop then the static table will stay in at least L2 cache, and if it's not called in a tight inner loop then the performance difference won't be important).

unsigned long mask2(unsigned param)
{
    static const unsigned long masks[] = {
        0x00000000UL, 0x00000001UL, 0x00000003UL, 0x00000007UL,
        0x0000000fUL, 0x0000001fUL, 0x0000003fUL, 0x0000007fUL,
        0x000000ffUL, 0x000001ffUL, 0x000003ffUL, 0x000007ffUL,
        0x00000fffUL, 0x00001fffUL, 0x00003fffUL, 0x00007fffUL,
        0x0000ffffUL, 0x0001ffffUL, 0x0003ffffUL, 0x0007ffffUL,
        0x000fffffUL, 0x001fffffUL, 0x003fffffUL, 0x007fffffUL,
        0x00ffffffUL, 0x01ffffffUL, 0x03ffffffUL, 0x07ffffffUL,
        0x0fffffffUL, 0x1fffffffUL, 0x3fffffffUL, 0x7fffffffUL,
        0xffffffffUL };

    if (param < (sizeof masks / sizeof masks[0]))
        return masks[param];
    else
        return 0xffffffffUL; /* Or whatever else you want to do in this error case */
}

It's worth pointing out that if you need the if() statement (because are worried that someone might call it with param > 32), then this doesn't win you anything over the alternative from the other answer:

unsigned long mask(unsigned param)
{
    if (param < 32)
        return (1UL << param) - 1;
    else
        return -1;
}

The only difference is that the latter version has to special case param >= 32, whereas the former only has to special case param > 32.

caf
  • 233,326
  • 40
  • 323
  • 462
  • to make it work when param == 32 is easy without creating a lookup table: [Set last `n` bits in unsigned int](https://stackoverflow.com/q/8128674/995714), [Creating a mask with N least significant bits set](https://stackoverflow.com/q/52573447/995714) – phuclv Oct 23 '20 at 06:32
4

How about this (in Java):

int mask = -1;
mask = mask << param;
mask = ~mask;

This way you can avoid lookup tables and hard coding the length of an integer.

Explanation: A signed integer with a value of -1 is represented in binary as all ones. Shift left the given number of times to add that many 0's to the right side. This will result in a 'reverse mask' of sorts. Then negate the shifted result to create your mask.

This could be shortened to:

int mask = ~(-1<<param);

An example:

int param = 5;
int mask = -1;        // 11111111 (shortened for example)
mask = mask << param; // 11100000
mask = ~mask;         // 00011111
broadbear
  • 614
  • 8
  • 19
  • 3
    Or, you could just do ~0 instead of -1. "int mask = ~(~0< – broadbear Jun 02 '16 at 01:37
  • This is completely valid also in C. But at least in C you need to add a suffix (`ull`) to make it valid for (almost) any type: `#define BITMASK_GEN(pos, len) (~(~0ull << len) << pos)`. This works for every type except for `unsigned __int128`. – alx - recommends codidact Mar 23 '20 at 21:53
2

From top of my head. Sorry, I'm on mobile. I assume a 64 bit type for clarity, but this can be easily generalized.

(((uint64_t) (bits < 64)) << (bits & 63)) - 1u

It's the typical (1 << bits) - 1 but branchless, with no undefined behavior, with the & 63 optimizable away on some platforms and with correct results for the whole range of values.

The left (left) shift operand becomes 0 for shifts bigger or equal than the type width.

The right (left) shift operand is masked to avoid undefined behavior, the value will never get bigger than 63. This is just to make compilers and language lawyers happy, as no platform will be adding ones when the left operand is already zero (for values bigger than 63). A good compiler should remove the & 63 masking on platforms where this is already the behavior of the underlying instruction (e.g. x86).

As we have seen, values bigger than 63 get a result of 0 from the shift, but there is a substraction by one afterwards leaving all bits set by an unsigned integer underflow, which is not undefined behavior on unsigned types.

Rafael Gago
  • 126
  • 1
  • 3
1

If you're worried about overflow in a C-like language with (1 << param) - 1 (when param is 32 or 64 at the max size type the mask becomes 0 since bitshift pushes past the bounds of type), one solution I just thought of:

const uint32_t mask = ( 1ul << ( maxBits - 1ul ) ) | ( ( 1ul << ( maxBits - 1ul ) ) - 1ul );

Or another example

const uint64_t mask = ( 1ull << ( maxBits - 1ull ) ) | ( ( 1ull << ( maxBits - 1ull ) ) - 1ull );

Here's a templatized version, keep in mind that you should use this with an unsigned type R:

#include <limits.h>     /* CHAR_BIT */

// bits cannot be 0
template <typename R>
static constexpr R bitmask1( const R bits )
{
    const R one = 1;
    assert( bits >= one );
    assert( bits <= sizeof( R ) * CHAR_BIT );
    const R bitShift = one << ( bits - one );
    return bitShift | ( bitShift - one );
}

Let's say max bits is 8 with a byte, with the first overflowing function we'd have 1 << 8 == 256, which when cast to byte becomes 0. With my function we have 1 << 7 == 128, which a byte can contain, so becomes 1<<7 | 1<<7 - 1.

I haven't compiled the function, so it may contain typos.


And for fun here's Julien Royer's fleshed out:

// bits can be 0
template <typename R>
static constexpr R bitmask2( const R bits )
{
    const R zero = 0;
    const R mask = ~zero;
    const R maxBits = sizeof( R ) * CHAR_BIT;
    assert( bits <= maxBits );
    return mask >> ( maxBits - bits );
}
leetNightshade
  • 2,673
  • 2
  • 36
  • 47
1

For a 32-bit mask you can use this (use uint64_t for a 64-bit mask):

#include <assert.h>
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>

int
main()
{
    size_t n = 8;
    assert(n <= 32);
    uint32_t mask = ~(uint32_t)0 >> (32 - n);

    printf("mask = %08" PRIX32 "\n", mask);
}

I know it's an answer to a very old post. But in case some human being actually reads this: I would welcome any feedback.

Michael Lehn
  • 2,934
  • 2
  • 17
  • 19
  • 1
    You can avoid the explicit `32`, here is a solution that works for all unsigned types and all values of `n` from `1` to the width of the type: `uint32_t mask = -1; mask = ~(mask << (n - 1) << 1);` – chqrlie Feb 07 '22 at 16:28
  • @chqrlie IMHO C does not guarantee that two's complement is used (Sure, purely academic nowadays). So -1 could be represented by something like 10...01 when the exotic machine uses sign and magnitude. – Michael Lehn Feb 09 '22 at 16:45
  • 1
    purely academic, but it does not matter how `-1` is represented as a signed int, when converted to an unsigned type, the value is the maximum value of the type and `uint32_t`, must have exactly 32 bits. – chqrlie Feb 09 '22 at 18:59
-1

Just for reference (google), I used the following to get an all 1 mask for for integral types.
In C++ one might simply use:

std::numeric_limits<uint_16t>::max() // 65535

Florian
  • 372
  • 2
  • 12
  • 2
    the question is about how to get a mask with N `1` bits on the right, not how to get all ones – phuclv Oct 23 '20 at 06:28