unsigned char DISPLAY_INSTRUCTIONS = 1;
Using an 8-bit value would allow us to have 28 possible values, or 256 unique flags. Each flag would take up a byte of resources, either on disk or in core RAM. We could also use other standard values for the flag like uint16_t, a 16-bit value storing up to 65,535 unique flags, probably way more than we could need or ever use. But what if we only had, say, 6 flags we needed to track? In the above scheme it would require six bytes, one byte for each flag, but using bit flags we could store all six flags (and then some) inside a single byte.
If you're unfamiliar with binary numbers, you might take a moment and read my instructable on number bases, which includes binary or find a number of tutorials online. I'll assume you already have a passing understanding of how binary numbers are put together. So, you may be asking how does one use the individual bits inside an integer as a flag for use in code/software? Typically, this is done by assigning a bit to "1" or "0" and based on its placement inside the integer, can be used for an affirmation or negation of the specified value. For example, take an 8-bit number, say, zero and look at it.
Ok, nothing exciting here. Now in the 1's location, make it 1:
We can do the same for the two's location:
or the four's location:
or maybe the 32 and 8th location:
What numbers do these bit flips make? We don't care. We're only concerned about the individual bits inside the number in this case. To easily assign flag values to bits, it's common to use the following idiom:
#define FLAG1 0x01 // 0000 0001
#define FLAG2 0x02 // 0000 0010
#define FLAG3 0x04 // 0000 0100
#define FLAG4 0x08 // 0000 1000
#define FLAG5 0x10 // 0001 0000
#define FLAG6 0x20 // 0010 0000
#define FLAG7 0x40 // 0100 0000
#define FLAG8 0x80 // 1000 0000
There we've defined our flags. Take note of the pattern in both the hexadecimal number and its binary representation. So, if FLAG5 is set, then the integer flag would have bit 5 set (using a 1-based index, contrary to the more common 0-based, but it's not important for us right now). Creating the flag variable and setting FLAG5 looks like this:
unsigned char myFlags = 0x00; myFlags |= FLAG5;
We OR the flags so that any existing flags will remain preserved. If you AND the flags, you will write over any existing flags with the bitmask your ANDing it to. This is useful when you want to clear a flag:
myFlags &= ~FLAG3;
The above sets FLAG3 to zero. Notice that you are ANDing with the complement of the flag.
But what happens if you have:
#define FLAG28 0x00400000