Home > Software engineering >  Bitwise operations and masks: return bit values of the original variable that are set in the mask
Bitwise operations and masks: return bit values of the original variable that are set in the mask

Time:07-11

It's my first time wondering here when the same question wasn't asked previously, therefore I have to ask it myself:)

There is a device (won't go in depth with that, since it's irrelevant for now) that I am working with where I have two inputs, which have length of 16 bits each. The 1st one of the inputs has the later needed values, and the 2nd one has the "locations" from where we want to find the values of 1st one's inputs. Let me show an example:

EDIT: clarification: the mask can be anything that's 16-bits in length and 8 bits set. Not just having the lowest two nibbles set (1), it's only so simple to just illustrate the scenario.

input:  0101 1011 0000 0111
mask:   0011 0011 0011 0011
output: 0001 0011 0000 0011

When mask is set at 1, the machine needs to return the input's value whether its 1 or 0, doesn't matter. The device uses the value regardless of that later on.

I can find solutions for this with simple &, as above, but it ain't enough since my hardware has its limitations and there are resources to be saved. As the example shows, the mask may have only contain at max 8 bits set since some things on the circuit board are mutually exclusive and I want to and can have my output to be only 8 bits in length:

output: xx01 xx11 xx00 xx11
saved to a variable as: 0111 0011

...I just don't know how, yet.

So how should I proceed, should I build on array where I save the locations of mask's set bits and then check value form the input, or is there a more efficient way to to this. Regarding scanning values etc. doesn't matter since I can handle that, at the moment we can treat the input and the mask just as any 16-bit long integers for example. In the short bit of code I used the same mock decimal values as I used in the binary examples earlier.

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

int main()
{
    uint16_t input=23303;   //1st input, gives the 1s and 0s to be extracted
    uint16_t mask=13107;    //2nd input, defines the locations of needed 1s and 0s
    uint8_t fi;             //Filtered inputs=input after masking, this one to be returned

    /*something needs to be done here*/

    return fi;              //With these inputs, this should be 115

    return 0;
}

CodePudding user response:

the mask can be anything that's 16-bits in length and 8 bits set. ...

Iterate through the result of input & mask and in every iteration check the mask bit set or not. If its set than set the corresponding bit in 8 bit result.

You can do:

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

int main (void) {
    uint16_t input = 23303;
    uint16_t mask = 13107;
    uint8_t fi = 0;
    uint16_t res = input & mask;
    
    for (unsigned int x = 0, c = 0; res; res >>= 1,   x) {
        if ((mask >> x) & 0x1) {
            if (res & 0x1) {
                fi |= 0x1 << c;
            } 
            c  ;
        }
    }

    printf ("fi : %" PRIu8 "\n", fi);
    return 0;
}

Output:

% ./a.out
fi : 115

Try out above solution with other mask values which are 16 bits in length and 8 bits set.

CodePudding user response:

The most easiest way:

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

    int main()
    {
        uint16_t input=23303;   //1st input, gives the 1s and 0s to be extracted
        uint16_t mask=13107;    //2nd input, defines the locations of needed 1s and 0s
        uint8_t fi;             //Filtered inputs=input after masking, this one to be returned
     
        /*something needs to be done here*/
        uint16_t temp = input & mask;
        uint8_t np0, np1, np2, np3;
        np0 = temp &0x03;
        np1 = (temp >> 4) & 0x03;
        np2 = (temp >> 8) & 0x03;
        np3 = (temp >> 12) & 0x03;
        
        fi = np0 | (np1 << 2) | (np2 << 4) | (np3 << 6);

        return fi;              //With these inputs, this should be 115

        return 0;
    }

A little bit complex but may faster: #include <stdio.h> #include <stdint.h>

    int main()
    {
        uint16_t input=23303;   //1st input, gives the 1s and 0s to be extracted
        uint16_t mask=13107;    //2nd input, defines the locations of needed 1s and 0s
        uint8_t fi;             //Filtered inputs=input after masking, this one to be returned
     
        /*something needs to be done here*/
        
        fi = (temp &0x03) | ((temp >> 2) & 0x0C) | ((temp >> 4) & 0x30) | ((temp >> 6) & 0xC0);

        return fi;              //With these inputs, this should be 115

        return 0;
    }
  •  Tags:  
  • c
  • Related