7

This question has been done to death, and I would agree that enums are the way to go. However, I am curious as to how enums compile in the final code- #defines are just string replacements, but do enums add anything to the compiled binary? Or are they both equivalent at that stage. When writing firmware and memory is very limited, is there any advantage, no matter how small, to using #defines?

Thanks!

EDIT: As requested by the comment below, by embedded, I mean a digital camera.

Thanks for the answers! I am all for enums!

Alexander Kondratskiy
  • 4,156
  • 2
  • 30
  • 51
  • 2
    "Embedded" can mean anything from a Nexus S to an avionics system. You should narrow it down (which chip, which compiler, which version?) if you want a meaningful answer. I agree with the answerers it *should* be treated similar to a `const`. – Matthew Flaschen Jan 09 '11 at 06:39
  • 1
    @Matthew: I think you're thinking of C++. In C, `#define` and `enum` can create constant expressions, but a `const` variable is never a constant expression, and accessing it will almost surely incur real code size and performance penalties (loading it from memory). – R.. GitHub STOP HELPING ICE Jan 09 '11 at 06:46
  • @R, you're right about a `const` not being a const expression in C99 (and I do need to read up on this). But in simple cases, the compiler can still avoid allocating memory for them. For instance, if I put `const int a = 1;` in a header, then `int b = a;` in main, the compiler *may* be smart enough not to allocate memory for `a`. – Matthew Flaschen Jan 09 '11 at 07:09
  • 2
    Usually the compiler will avoid this type of smarts for the sake of compatibility with traditional linker hacks that might override the symbol. – R.. GitHub STOP HELPING ICE Jan 09 '11 at 08:11
  • 3
    @Mathew: I don't think the question is particularly specific to 'embedded' in any case, and which chip/compiler or whatever should make little no difference, it is a more general question. – Clifford Jan 09 '11 at 09:58

3 Answers3

10

Both are constant expressions in the terminology of the standard, so they "should" be evaluated fully at compile-time by any sane compiler. It would take a maliciously pathological compiler to generate different code.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • 1
    they are not only *constant expressions* but *integer constant expressions* in the terminology of the standard. The difference is important here, since for the first e.g an address constant would also qualify. Only by being the later, they may appear in type declarations and for the definition of other `enum` constants. And used as array length they make the difference between plain arrays and VLA. – Jens Gustedt Jan 09 '11 at 08:59
  • @nqtronix: I don't see how that comment relates to my answer (or to the question). – R.. GitHub STOP HELPING ICE Feb 03 '19 at 21:58
  • @R.. My bad, I meant to comment on the answer below. I fixed it and added clarification. – nqtronix Feb 05 '19 at 07:49
5

An enum is just an integer, ultimately. The compiler propagates the values, just as it would for a const.

chrisaycock
  • 36,470
  • 14
  • 88
  • 125
  • 1
    an `enum` value is a *constant expression*, whereas a `const` variable (in C) is not and thus can't be used for static initialization, `case` labels, ...; an `enum` value is a compile-time constant, a `const` variable is a runtime constant (from the perspective of the language - the compiler is free to do constant propagation for `const` variables) – Christoph Jan 09 '11 at 10:09
  • An enum is just an 'int', specifically. At least GCC treats enums by default as a 32bit value, even on 16bit or 8bit MCUs. To use the smallest possible type, one must specify the -fshort-enums option for compiling. – nqtronix Feb 05 '19 at 07:43
  • (to late for edit) This is especially importent when used as a function argument: `func(enum value)` compiles worse (by default) than `func(unit8_t value)` and passing a #defined value. – nqtronix Feb 05 '19 at 07:48
4

It's impossible to say without profiling or measuring in some other manner.

BUT, any decent compiler will not show any significant difference. Furthermore, you should always prefer readable, typesafe code over efficient, unreadable, gotcha-ridden code. Don't start optimizing for efficiency over readability until you have proven two things:

  1. you actually need the efficiency boost
  2. the part of the program you're changing has been shown to be a bottleneck by a profiler.
Philip Potter
  • 8,975
  • 2
  • 37
  • 47
  • 2
    I completely agree with you about unneeded optimization! I just joined a project and #define was being used, so I was wondering if there could an efficiency reason. – Alexander Kondratskiy Jan 09 '11 at 06:49
  • In this case, you probably don't need to do profiling and measuring as such -- just look at the generated assembly, which should be identical. – Brooks Moses Jan 09 '11 at 08:39