Best way to unset a flag in C when using Enum that is signed

360 Views Asked by At

I'm trying to use enum in C to create a flags variable, as discussed here: Flags, enum (C)

How should I reset a single enum flag, when the compiler represents the enum as signed?

Problem:

Say I declare my flags type like this:

typedef enum {       
     FLAGS_A = 1 << 0,
     FLAGS_B = 1 << 1,
     FLAGS_C = 1 << 2,
     FLAGS_D = 1 << 3     
} flags_t;

flags_t flags;

I would like to reset a flag like this:

flags |=   FLAGS_A;   // Set A
flags &= (~FLAGS_A);  // Reset A

However the compiler (Microchip XC8 Compiler V2.32) throws an error because bitwise operators should only be used on unsigned types. It looks like the enum is actually a signed integer under the hood.

Based on this question, it looks like there's no good way to force the compiler to use unsigned for enum: Is there a way to make an enum unsigned in the C90 standard? (MISRA-C 2004 compliant)

Things I've Tried:

One workaround I found was to add a special enumerated variable that has all the other flags set. I can use that as a mask to reset flag A:

typedef enum {
     ....
     FLAGS_RESET_A  = (FLAGS_B | FLAGS_C | FLAGS_D) 
} flags_t

flag_t flags &= (FLAGS_RESET_A);  // Reset A 

This workaround is cumbersome. Any time I modify the flags type, such as adding a flag, I also have to remember to modify all the reset masks. I'm hoping there is a method that preserves the enum as a "single source of truth" for the flag definitions.

Another workaround is type casting to an unsigned integer, but that defeats the safety of using an enumerated type.

0

There are 0 best solutions below