Alex Rivera | Logout

Flags, enum (C)

Asked 2009-10-27T14:40:11.007
19

I'm not very used to programming with flags, but I think I just found a situation where they'd be useful:

I've got a couple of objects that register themselves as listeners to certain events. What events they register for is dependent on a variable that is sent to them when they are constructed. I think a nice way to do this would be to send bitwise OR connected variables, like such: TAKES_DAMAGE | GRABBABLE | LIQUID, etc. Then, in the constructor, the object can check what flags are set and register it self as listener for the ones that are.

But this is where I get confused. Preferably, the flags would be in an enum. But that is also a problem. If we have got these flags:

enum
{
    TAKES_DAMAGE,/* (0) */
    GRABBABLE, /* (1) */
    LIQUID, /* (2) */
    SOME_OTHER /* (3) */
};

Then sending the flag SOME_OTHER (3) will be the same as sending GRABBABLE | LIQUID, will it not?

How exactly do you deal with this stuff?

Edit
Report

2 Answers

62

Your enumeration needs to be powers of two :

enum
{
    TAKES_DAMAGE = 1,
    GRABBABLE = 2,
    LIQUID = 4,
    SOME_OTHER = 8
};

Or in a more readable fashion :

enum
{
    TAKES_DAMAGE = 1 << 0,
    GRABBABLE = 1 << 1,
    LIQUID = 1 << 2,
    SOME_OTHER = 1 << 3
};

Why ? Because you want to be able to combine flags with no overlapping, and also be able to do this:

if(myVar & GRABBABLE)
{
    // grabbable code
}

... Which works if the enumeration values look like this :

 TAKES_DAMAGE: 00000001
 GRABBABLE:    00000010
 LIQUID:       00000100
 SOME_OTHER:   00001000

So, say you've set myVar to GRABBABLE | TAKES_DAMAGE, here's how it works when you need to check for the GRABBABLE flag:

 myVar:     00000011
 GRABBABLE: 00000010 [AND]
 -------------------
            00000010 // non-zero => converts to true

If you'd set myVar to LIQUID | SOME_OTHER, the operation would have resulted in :

 myVar:     00001100
 GRABBABLE: 00000010 [AND]
 -------------------
            00000000 // zero => converts to false
answered 2009-10-27T14:42:21.533
3

you need

enum
{
    TAKES_DAMAGE = 1,
    GRABBABLE = 2,
    LIQUID = 4,
    SOME_OTHER = 8
};
answered 2009-10-27T14:42:31.957

Your Answer