Enumeration vs #define

Started by
11 comments, last by Washu 14 years, 5 months ago
Quote:Original post by Rattenhirn
Quote:Original post by RandomBystander
AFAIK, they also optimize better than const ints.

What makes you think that?


Probably because const is one of the subtle differences between C and C++. In C, const variables default to extern linkage and are not officially constants (so they can't, for example, be used to specify the length of an array in C89) so, in C, there are more contexts where a const variable will have to be treated as a regular variable by the compiler than in C++. Good practice in C isn't always good practice in C++ (and vice versa).

Quote:Original post by Ravyne
A #define, used as a constant, is roughly equivilent to a C or C++ 'const' variable except... it's address cannot be taken via the & operator


Also true of enum values.

Quote:
And the final kicker is that you can't use the string "PLASMA" anywhere in your code, or it'll be replaced by "3"


The text-replacement is smart enough to understand tokens and strings, so myPLASMA and "PLASMA string" will not be converted to my3 and "3 string". The problem is mostly with errors (You'll get a better error for "int BAR = 0;" if BAR is an enum value than if BAR is a #define constant) and with namespaces (the text-replacement isn't smart enough to understand namespaces).

Quote:
Also, no more multiplying that Matrix by PLASMA, unless you specifically define such an operation taking eMatterState as its parameter.


I don't know a lot about C++ conversions with functions, but 'g++ -Wall' doesn't even issue a warning if you multiply an enum value with a double. So, you can easily get an int from an enum, but you need a cast to go the other way around.
Advertisement
Roughly: In ANSI C, constants should be #defines, in C99 constants should be enum members for integers (or more #defines), in C++ constants should be variables with the const keyword or enum members if logical grouping of integers is desired.

Either way, in C++ there's no reason to use #define for constants unless you're trying to keep a header compatible with C. Enums and const variables are semantically safer.
Wow, the answer is very clear. I was expecting everyone to say something about #define being better because my C++ teacher said it was, but I didn't understand why. I think she didn't want to talk about enums at the time or something, but I'll take the word of anyone here at gd.net over her word.

Thanks a lot. I can't believe it is so plain to see, I'll have to think a little harder before posting next time!
--Dbproguy - My Blog - Tips, Opinions and Reviews about C++, Video Games, and Life
Quote:Original post by Ravyne
Quote:Original post by Rattenhirn
Quote:Original post by RandomBystanderAFAIK, they also optimize better than const ints.


What makes you think that?



It depends on the situation.

In general, the compiler will, most of the time, simply inline a const int value as if it were a literal int, however, it is free not to do so. This is because a const int must reside in memory because its address can be taken via the '&' operator (though I wonder if the compiler is free to do away with that if its address is never taken).

With the right settings the compiler will remove entire functions if they're not used. Calling the few bytes you could possibly save when dealing with a dumb or badly configured optimizer is like calling a pea a three course meal. Sure, there's the first third... the second third... and the third third... but it's not nearly as filling as implied [lol]
Quote:Original post by Ravyne
A #define, used as a constant, is roughly equivilent to a C or C++ 'const' variable except, of course, that it is not typed, that it is inserted through text replacement, and that it's address cannot be taken via the & operator (because a #define never actually exists in memory at runtime).

An enumeration defines a category of related constants, which together constitute a new, distinct type. This means that type safety applies in full, and consequently that enumeration members from other enums and literal values cannot be assigned to the enum type, even when the constant values they represent may be identical to those in the target enumeration.

True in C++, not in C. In C:
enum color { red, green, blue };color c = 1; // valid in C, not in C++

Quote:
In C, you'd wrap that up in an appropriate typedef, IIRC. Anyhow, now your functions dealing with the state of matter can take a parameter of type "eMatterState", so it can only take one of SOLID, LIQUID, GAS or PLASMA -- There is no way to pass -1 or 17, or even 0, 1, 2, or 3 without going through the eMatterState type. Also, no more multiplying that Matrix by PLASMA, unless you specifically define such an operation taking eMatterState as its parameter.

Not necessarily true, in C and C++ enumeration types are subject to integral promotion rules. Thus:
int i = green * 4; //valid in C and C++

Finally, the value of an enumeration can be specified through the use of explicit conversion from another expression of enumeration or arithmetic type. It will take on the appropriate value within the enumeration, unless it is outside of the bounds of those values defined by the enumeration, in which case the value is unspecified (note: not undefined behavior).

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.

This topic is closed to new replies.

Advertisement