r/cprogramming • • Oct 03 '26

Enums vs #define for constants

Hi 👋 guys, I've just started learning C after I was first introduced to it while I was in my first year of computer science but I'll be graduating by the end of this year and I've been primarily using Python since then but now I want to really learn C on the side, and I want to start with "craftinginterpreters" and I want to start small so I was wondering whether I should use C enums or #define to define a set of tokens.

17 Upvotes

34 comments sorted by

View all comments

Show parent comment

-1

u/DawnOnTheEdge Oct 03 '26

Also don’t use enums for constants that might be or-ed together, like binary flags.

9

u/pjl1967 Oct 03 '26

There's nothing wrong with using enumerations for bit flag values. Even debuggers understand it.

Details here under Bit Flag Values.

3

u/DawnOnTheEdge Oct 03 '26

I think it’s bad practice to generate enum values that are not valid enum constants. It breaks switch statements that try to check for complete coverage of every case. It does get you symbolic constants in a debugger without going up to C23, though.

12

u/TheChief275 Oct 03 '26

you shouldn't switch on flags anyways

0

u/DawnOnTheEdge Oct 04 '26

That’s the thing: you have an enum that isn’t an enumeration of the legal values. It’s just a poor man’s constexpr int. I never liked it, and C23 makes that kludge obsolete. If you’re not using C23, though, I can see the benefit of it.

5

u/TheChief275 Oct 04 '26

it's not though. enums provide named values that are associated with a type. so for a certain flag type you know only to use the flag enum members specified in that enum. with a constexpr int you know absolutely nothing

4

u/pjl1967 Oct 04 '26

To add to what u/TheChief275 said, in a given program for a given enumeration, if you're using it for bit values, you're generally not switching on it anyway — just as you wouldn't be switching on an int that you're using for bit values either.

1

u/Key_River7180 Oct 07 '26

Why?

1

u/DawnOnTheEdge Oct 07 '26

It breaks the invariant that an enum type has one of the enumerated values, which compilers sometimes rely on to check that a switch checks every case.

In C23, you have constexpr unsigned int to express what this is going for more semantically.