Recipe3.9.Turning Bits On or Off


Recipe 3.9. Turning Bits On or Off

Problem

You have a numeric value or an enumeration that contains bit flags. You need a method to turn on (set the bit to 1) or turn off (set the bit to 0) one or more of these bit flags. In addition, you also want a method to flip one or more bit flag values; that is, change the bit(s) to their opposite value.

Solution

The following method turns one or more bits on using a bit flag passed in to the bitToTurnOn parameter:

 public static int TurnBitOn(int value, int bitToTurnOn) {    return (value | bitToTurnOn); } 

The following method turns one or more bits off using a bit flag passed in to the bitToTurnOff parameter:

 public static int TurnBitOff(int value, int bitToTurnOff) {    return (value & ~bitToTurnOff); } 

The following method flips a bit to its opposite value using a bit flag passed in to the bitToFlip parameter:

 public static int FlipBit(int value, int bitToFlip) {    return (value ^ bitToFlip); } 

The following method turns one or more bits on using a numeric bit position value passed in to the bitPosition parameter:

 public static int TurnBitPositionOn(int value, int bitPosition) {    return (value | (1 << bitPosition)); } 

The following method turns one or more bits off using a numeric bit position value passed in to the bitPosition parameter:

 public static int TurnBitPositionOff(int value, int bitPosition) {    return (value & ~(1 << bitPosition)); } 

The following method flips a bit to its opposite value using a numeric bit position value passed in to the bitPosition parameter:

 public static int FlipBitPosition(int value, int bitPosition) {    return (value ^ (1 << bitPosition)); } 

Discussion

When a large number of flags are required, and particularly when combinations of flags can be set, it becomes cumbersome and unwieldy to use Boolean variables. In this case, using the binary representation of a number, you can assign each bit to indicate a specific Boolean value. Each Boolean value is called a bit flag. For example, you have a number defined as a byte data type. This number is comprised of eight binary bit values, which can be either a 1 or a 0. Supposing you assign a color to each bit, your number would be defined as follows:

 byte colorValue = 0; // colorValue initialized to no color // colorValue      Bit position // red         0 (least-significant bit) // green       1 // blue        2 // black       3 // grey        4 // silver      5 // olive       6 // teal        7 (most-significant bit) 

By setting each bit to 0 or 1, you can define a color value for the colorValue variable. Unfortunately, the colorValue variable does not take into account all colors. You can remedy this by allowing multiple bits to be set to 1. This trick allows you to combine red (bit 0) and green (bit 1) to get the color yellow; red (bit 0) and blue (bit 2) to get violet; or red, green, and blue to get white.

The colorValue bit mask is defined as a byte. This is because it is more convenient to use unsigned data types for bit flag variables. The other unsigned integers supported by C# are ushort, uint, and ulong. This makes it easier to create the bit mask values to use with the bit flag variable. Simply put, you do not have to worry about negative values of the data type when using unsigned data types. Be aware, though, that the ushort, uint, and ulong types are not CLS-compliant.


Now that you have your bit flags set up in the colorValue variable, you need a way to set the individual bits to a 0 or 1, as well as a way to determine whether one or more bits (colors) are turned on. To do this, you use a bit mask. A bit mask is a constant number, usually of the same type as the target type containing the bit flags. This bit mask value will be ANDed, ORed, or XORed with the number containing the bit flags to determine the state of each bit flag or to set each bit flag to a 0 or 1:

 [Flags] public enum ColorBitMask {    NoColorBitMask = 0,   //binary value == 00000000    RedBitMask = 1,       //binary value == 00000001    GreenBitMask = 2,     //binary value == 00000010    BlueBitMask = 4,      //binary value == 00000100    BlackBitMask = 8,     //binary value == 00001000    GreyBitMask = 16,     //binary value == 00010000    SilverBitMask = 32,   //binary value == 00100000    OliveBitMask = 64,    //binary value == 01000000    TealBitMask = 128,    //binary value == 10000000    YellowBitMask = 3,    //binary value == 00000011    VioletBitMask = 5,    //binary value == 00000101    WhiteBitMask = 7,     //binary value == 00000111 } 

One common use for the & operator is to set one or more bits in a bit flag value to 0. If you AND a binary value with 1, you always obtain the original binary value. If, on the other hand, you AND a binary value with 0, you always obtain 0. Knowing this, you can use the bit mask values to remove various colors from the colorValue variable:

 ColorBitMask color = ColorBitMask.YellowBitMask; ColorBitMask newColor = color & ~ColorBitMask.RedBitMask; 

This operation removes the RedBitMask from the color value. This value is then assigned to the newColor variable. The newColor variable now contains the value 2 (00000010 in binary), which is equal to the GreenBitMask value. Essentially, you removed the color red from the color yellow and ended up with the color green, which is a constituent color of yellow.

The | operator can also be used to set one or more bits to 1. If you OR a binary value with 0, you always obtain the original binary value. If, on the other hand, you OR a binary value with 1, you always obtain 1. Using this knowledge, you can use the bit mask values to add various colors to the color variable. For example:

 ColorBitMask color = ColorBitMask.RedBitMask; ColorBitMask newColor = color | ColorBitMask.GreenBitMask; 

This operation ORs the GreenBitMask to the color value, which is currently set to the value RedBitMask. This value is then assigned to the newColor variable. The newColor variable now contains the value 3 (00000011 in binary); this value is equal to the YellowBitMask value. Essentially, you added the color green to the color red and obtained the color yellow.

The ^ operator is often used to flip or invert one or more bits in a bit flag value. It returns a 1 only when either bit is set to 1. If both bits are set to 1s or 0s, this operator returns a 0. This operation provides a convenient method of flipping a bit:

 ColorBitMask color = ColorBitMask.RedBitMask; ColorBitMask newColor = color ^ ColorBitMask.RedBitMask; 

The code shown here flips the least-significant bit (defined by the RedBitMask operation) to its opposite value. So if the color were red, it would become 0, or no defined color, as shown here:

   00000001 == Color (red) ^ 00000001 == RedBitMask   00000000 

If you XOR this result a second time with the bit mask RedBitMask, you get your original color (red) back again, as shown here:

   00000000 == Color (red) ^ 00000001 == RedBitMask   00000001 == red 

If this operation is performed on the color yellow, you can obtain the color other than red that makes up this color. This operation is shown next along with the code.

 ColorBitMask color = ColorBitMask.YellowBitMask; ColorBitMask newColor = color ^ ColorBitMask.RedBitMask;     00000011 == Color (yellow)   ^ 00000001 == RedBitMask   00000010 == green 

Use the AND (&) operator to set one or more bits to 0. Use the OR (|) operator to set one or more bits to 1. Use the XOR (^) operator to flip one or more bits to their opposite values.


See Also

See Recipe 1.4; see the "C# Operators" topic in the MSDN documentation.



C# Cookbook
Secure Programming Cookbook for C and C++: Recipes for Cryptography, Authentication, Input Validation & More
ISBN: 0596003943
EAN: 2147483647
Year: 2004
Pages: 424

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net