How do flags work in C?

20,049

Solution 1

You need to offset the bits, otherwise there's no way to extract the individual flags. If you had flags corresponding to 1, 2, 3, & 4, and a combined value of 5, how could you tell if it was 2 & 3 or 1 & 4?

You can also do it this way, for example:

enum {
    FIRST = 1 << 0, // same as 1
    SECOND = 1 << 1, // same as 2, binary 10
    THIRD = 1 << 2, // same as 4, binary 100
    FOURTH = 1 << 3 // same as 8, binary 1000
};

Then you combine flags like so:

int flags = FIRST | THIRD | FOURTH;

And you extract them like this:

if (flags & THIRD) { ...

Solution 2

Your first method isn't using the bits in the most efficient manner. In the first example you are using hexadecimal notation and it is equivalent to:

TEXTUREFLAGS_POINTSAMPLE = 1,
TEXTUREFLAGS_TRILINEAR = 16,

In the second method it appears that you are just increasing by one each time. This won't work when you combine flags, because the combined value could be the same as another flag (for example, 1 | 2 == 3).

You should use these values instead:

0x00000001  // == 1
0x00000002  // == 2
0x00000004  // == 4
0x00000008  // == 8
0x00000010  // == 16
0x00000020  // == 32
0x00000040  // == 64
etc...

These are the powers of two and they can be combined using bitwise-or in any way without giving collisions.

Solution 3

Flags like this are binary values, so you can combine 1, 2, 4, 8, 16, 32, 64, 128 in a single byte, or further powers of 2 up to 2^31 in an int. Because they're binary values, you can "or" them together, so if you "or" together 1,2,4 you end up with 7, for example. And you can extract the bit you want using "and" - so if you have an int with some flags or'ed together, and you want to see if the "4" bit is set, you can say if (flag & 4) and it will be true if the "4" bit is set.

Solution 4

Think of the flags as an array of 32 bits (booleans)

To turn one of these bits on you OR it with 1 << BitIndex (where BitIndex is zero-based, so 0 - 31) To turn one off you AND it with ~(1 << BitIndex) To check if it's on or off you AND it with (1 << BitIndex)

Once you get over the difference between digital OR/AND against logical OR/AND it'll all click. Then you'll appreciate hexadecimal notation!

Share:
20,049
Justin Meiners
Author by

Justin Meiners

Updated on April 03, 2020

Comments

  • Justin Meiners
    Justin Meiners about 4 years

    Recently I have come across several examples of "flags" in C and C++, and I don't quite understand how they work. After looking at some source code I noticed that often flag values are defined in hexadecimal such as the following:

    FLAG1 = 0x00000001,
    FLAG2 = 0x00000010,
    

    My intuitive suggests that these values are being combined. Do flags work by combining all the flags values into one int? If I had used both of these like FLAG1 | FLAG2 would the result be 0x00000011?

    Do I need to create enums with bit offsets or can I use ascending integers Like:

    FLAG1 = 1;
    FLAG2 = 2;