How do flags work in C?
Asked Answered
C

4

16

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;
Charlie answered 4/9, 2010 at 19:25 Comment(0)
B
41

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) { ...
Bluebill answered 4/9, 2010 at 19:29 Comment(0)
I
12

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.

Imperception answered 4/9, 2010 at 19:28 Comment(3)
Ok but it won't work if I just do one to like 20 will it? I still have to stagger the hexidecimal so they don't overwrite eachother right? Or am I not understanding how it works.Charlie
@user425756, if you don't use powers of two, you can't tell the difference between the 1 and the 2 being set, or 3 being set.Wanton
Yeah thats what I was thinking.Charlie
W
7

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.

Wanton answered 4/9, 2010 at 19:32 Comment(1)
Thank you that makes more sense.Charlie
G
5

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!

Gillen answered 4/9, 2010 at 19:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.