Use Bit Flags

I have seen many programmers use dozens of chart-sized variables or Booleans to store simple on or off flags. This is a tremendous waste of space, as you only need a single bit to represent the true or false value of a flag. Instead, I like to use a lot of bit flags. Here is a hypothetical example:

We have a sprite structure for our game. This structure needs to keep track of whether the sprite is invisible and if the sprite can be collided against. If you were to have one member per flag, your structure might look like this:

typdef struct sprite_s
{
.
.
.
char nHidden
char nCollide
.
.
.

} sprite_t;
Sure, you are pretty crafty using bytes instead of whole integers to store this flag. But if you use bit flags, you can reduce this by half:

#define BITFLAG_HIDDEN 0x01
#define BITFLAG_COLLIDE 0x02

typdef struct sprite_s
{
.
.
.
unsigned char nFlags
.
.
.
} sprite_t;
Now we only need a single character, nFlags, to hold both flags. A byte is 8 bits. We use two of these to represent the hidden and collision states. For instance, if we want to set the hidden bit, simply OR in the bit flag defined up top:

nFlags |= BITFLAG_HIDDEN;

Now, the first bit is turned on. If we want to turn this bit on, we AND the flags with the inverse of the bit flag that we wish to remove:

nFlags &= ~BITFLAG_HIDDEN;
The first bit is now cleared. The great thing is that we can combine the flags like this:

nFlags |= (BITFLAG_HIDDEN | BITFLAG_COLLISION);
To determine if a bit flag is turned on, use the bitwise AND operation:

if (nFlags & BITFLAG_HIDDEN)
return;
In this case, bail out of the function if the sprite is not visible. This code fragment would be something that you may see in a sprite drawing loop.

Of course, we have only defined two bit flags. A byte can hold 8. If you need more, you can use a short for 16 bits or an integer for 32 bits. Make sure you define the flags field as unsigned. Otherwise, you will have issues reading the values in the debugger when you turn on the sign bit.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다