简体   繁体   中英

Controlling bits in a ushort array

I would like to know how I can read and write specific bits efficiently to a ushort integer.

The methods would be something like so:

// Sets the bit positioned at bitNumber in the ushort integer b
// to be either 1 or 0 depending on state.
public ushort SetBit(ushort b, int bitNumber, bool state)
{
   ushort result = b;
   // Code to set the specific bit in ushort result.
   return result
}
// Returns the value of the bit in position bitNumber from the 
// ushort b as a true or false.
public bool GetBit(ushort b, int bitNumber)
{
   bool stateOfBit = false;
   // Code to read the bit into stateOfBit.
   return stateOfBit;
}

I have tried using BitArray class but it only takes a byte or a 32 bit integer.

Does someone know how to do this?

Thanks

First you need to guard against invalid bitNumber values by making sure it is between 1 and 16.

Then for setting you either want to "OR" it with a mask that has that bit set to one (by left shifting 1 to the desired position) if state is true. Otherwise you "AND" it with a mask where all the bits are 1 except the one you want to set to zero (accomplished by NOT-ing the other mask).

For determining if the bit is set just "AND" it to the first mask mentioned and compare to zero.

public static ushort SetBit(ushort b, int bitNumber, bool state)
{
    if(bitNumber < 1 || bitNumber > 16)
        throw new ArgumentOutOfRangeException("bitNumber", "Must be 1 - 16");

    return state ? 
        (ushort)(b | (1 << (bitNumber - 1))) : 
        (ushort)(b & ~(1 << (bitNumber - 1)));
}

public static bool GetBit(ushort b, int bitNumber)
{
    if (bitNumber < 1 || bitNumber > 16)
        throw new ArgumentOutOfRangeException("bitNumber", "Must be 1 - 16");

    return (b & (1 << (bitNumber - 1))) > 1;
}

This assumes that you want bitNumber to be one-based from the least significant bit, or right most bit. If you want zero-based just remove the - 1 used after bitNumber in all the code and adjust the if statement accordingly. To make this start from the most significant or left most bit then just subtract 16 from bitNumber instead of 1 for one-based, or subtract 15 for zero-based.

ushort s = 0;
//set the 5th bit from the right to true
s |= 1 << 5;
//set the 5th bit from the right to false
//~ will return a negative number, so casting to int is necessary
int i = s;
i &= ~(1 << 5);
s = (ushort)i;

To do this in a method, you can either have the method return it or pass the ushort by reference:

public void SetBit(ref ushort b, int bitNumber, bool state) {
    if (bitNumber < 0 || bitNumber > 15)
        //throw an Exception or return
    if (state) {
        b |= (ushort)(1 << bitNumber);
    } else {
        int i = b;
        i &= ~(1 << bitNumber);
        b = (ushort)i;
    }
}

public bool GetBit(ushort b, int bitNumber) {
    if (bitNumber < 0 || bitNumber > 15)
        //throw an Exception or just return false
    return (b & (1 << bitNumber)) > 0;
}

To count bitNumber from the left, you need 15 - bitNumber

I really liked juharr's answer (it looks cleaner and has less variable creation), but it is not right. The last check should be ( > 0 ) not ( > 1 ).

public static ushort SetBit(ushort b, int bitNumber, bool state)
{
    if(bitNumber < 1 || bitNumber > 16)
        throw new ArgumentOutOfRangeException("bitNumber", "Must be 1 - 16");

    return state ? 
        (ushort)(b | (1 << (bitNumber - 1))) : 
        (ushort)(b & ~(1 << (bitNumber - 1)));
}

public static bool GetBit(ushort b, int bitNumber)
{
    if (bitNumber < 1 || bitNumber > 16)
        throw new ArgumentOutOfRangeException("bitNumber", "Must be 1 - 16");

    return (b & (1 << (bitNumber - 1))) > 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM