Can someone explain how this bitmask works?

This is the code that my partner came up with, but for some reason I can not hold it to ask him how it should work. I went through this many times now and it seems I can’t get the answer that I think I should get.

/**
 * bitMask - Generate a mask consisting of all 1 
 *   lowbit and highbit
 *   Examples: bitMask(5,3) = 0x38
 *   Assume 0 <= lowbit <= 31, and 0 <= highbit <= 31
 *   If lowbit > highbit, then mask should be all 0's
 *   Legal ops: ! ~ & ^ | + << >>
 */
int bitMask(int highbit, int lowbit) {
   int i = ~0;
   return ~(i << highbit << 1) & (i << lowbit);
}
+4
source share
2 answers

This function is actually incorrect: for large values, highbitand lowbitthis may have specific behavior for implementation or even undefined behavior. It should use and return types unsigned:

unsigned bitMask(int highbit, int lowbit) {
    unsigned i = ~0U;
    return ~(i << highbit << 1) & (i << lowbit);
}

Here are the steps:

  • i = ~0U; I sets to all bits 1.

  • i << highbit , highbit 0 .

  • i << highbit << 1 0 . i << (highbit + 1), , highbit + 1 i.

  • ~(i << highbit << 1) , highbit + 1, , 0 .

  • i << lowbit lowbit 0 1 .

  • ~(i << highbit << 1) & (i << lowbit) , 1 lowbit highbit , 0 .

:

  • bitMask(31, 0)0xFFFFFFFF.
  • bitMask(0, 0)0x00000001.
  • bitMask(31, 16)0xFFFF0000.
  • bitMask(15, 0)0x0000FFFF.

. , , -:

unsigned bitSpec(int start, int len) {
    return (~0U >> (32 - len)) << start;
}

:

  • bitSpec(0, 32)0xFFFFFFFF.
  • bitSpec(0, 1)0x00000001.
  • bitSpec(16, 16)0xFFFF0000.
  • bitSpec(0, 16)0x0000FFFF.
+3

, , , , , , . , int unsigned int. . ( C).

unsigned , , :

:

#include <stdio.h>
#include <stdlib.h>

unsigned int bitMask (unsigned int highbit, unsigned int lowbit) {
    unsigned int i = ~0;
    return ~(i << highbit << 1) & (i << lowbit);
}

char *binstr (unsigned long n, unsigned char sz, unsigned char szs, char sep) {

    static char s[128 + 1] = {0};
    char *p = s + 128;
    unsigned char i;

    for (i = 0; i < sz; i++) {
        p--;
        if (i > 0 && szs > 0 && i % szs == 0)
            *p-- = sep;
        *p = (n >> i & 1) ? '1' : '0';
    }

    return p;
}

int main (int argc, char **argv) {

    unsigned high = argc > 1 ? (unsigned)strtoul (argv[1], NULL, 10) : 5;
    unsigned low  = argc > 2 ? (unsigned)strtoul (argv[2], NULL, 10) : 3;

    printf ("%s\n", binstr (bitMask (high, low), 32, 8, '-'));

    return 0;
}

$ ./bin/bitmask
00000000-00000000-00000000-00111000

$ ./bin/bitmask 10 3
00000000-00000000-00000111-11111000

$ ./bin/bitmask 31 5
11111111-11111111-11111111-11100000

$ ./bin/bitmask 4 8
00000000-00000000-00000000-00000000
0

Source: https://habr.com/ru/post/1626714/


All Articles