"static const" vs "#define" vs "enum"
It depends on what you need the value for. You (and everyone else so far) omitted the third alternative:
static const int var = 5;
#define var 5
enum { var = 5 };
Ignoring issues about the choice of name, then:
- If you need to pass a pointer around, you must use (1).
- Since (2) is apparently an option, you don't need to pass pointers around.
- Both (1) and (3) have a symbol in the debugger's symbol table - that makes debugging easier. It is more likely that (2) will not have a symbol, leaving you wondering what it is.
- (1) cannot be used as a dimension for arrays at global scope; both (2) and (3) can.
- (1) cannot be used as a dimension for static arrays at function scope; both (2) and (3) can.
- Under C99, all of these can be used for local arrays. Technically, using (1) would imply the use of a VLA (variable-length array), though the dimension referenced by 'var' would of course be fixed at size 5.
- (1) cannot be used in places like switch statements; both (2) and (3) can.
- (1) cannot be used to initialize static variables; both (2) and (3) can.
- (2) can change code that you didn't want changed because it is used by the preprocessor; both (1) and (3) will not have unexpected side-effects like that.
- You can detect whether (2) has been set in the preprocessor; neither (1) nor (3) allows that.
So, in most contexts, prefer the 'enum' over the alternatives. Otherwise, the first and last bullet points are likely to be the controlling factors — and you have to think harder if you need to satisfy both at once.
If you were asking about C++, then you'd use option (1) — the static const — every time.
Generally speaking:
static const
Because it respects scope and is type-safe.
The only caveat I could see: if you want the variable to be possibly defined on the command line. There is still an alternative:
#ifdef VAR // Very bad name, not long enough, too general, etc..
static int const var = VAR;
#else
static int const var = 5; // default value
#endif
Whenever possible, instead of macros / ellipsis, use a type-safe alternative.
If you really NEED to go with a macro (for example, you want __FILE__
or __LINE__
), then you'd better name your macro VERY carefully: in its naming convention Boost recommends all upper-case, beginning by the name of the project (here BOOST_), while perusing the library you will notice this is (generally) followed by the name of the particular area (library) then with a meaningful name.
It generally makes for lengthy names :)
In C, specifically? In C the correct answer is: use #define
(or, if appropriate, enum
)
While it is beneficial to have the scoping and typing properties of a const
object, in reality const
objects in C (as opposed to C++) are not true constants and therefore are usually useless in most practical cases.
So, in C the choice should be determined by how you plan to use your constant. For example, you can't use a const int
object as a case
label (while a macro will work). You can't use a const int
object as a bit-field width (while a macro will work). In C89/90 you can't use a const
object to specify an array size (while a macro will work). Even in C99 you can't use a const
object to specify an array size when you need a non-VLA array.
If this is important for you then it will determine your choice. Most of the time, you'll have no choice but to use #define
in C. And don't forget another alternative, that produces true constants in C - enum
.
In C++ const
objects are true constants, so in C++ it is almost always better to prefer the const
variant (no need for explicit static
in C++ though).