17

In both c and c++ enum could be defined with tag

enum e_smth {
    smth_one,
    smth_two,
    smth_err
};

or without tag

enum {
    smth_one,
    smth_two,
    smth_err
};

If it was defined with tag it makes sense in switch statements in both c and c++ :

e_smth some_var;
....//do some stuff with some_var
switch (some_var)
{
case smth_one:
break;
case smth_two:
break;
}

will produce -Wswitch warning if this will be compiled with gcc or g++.

It makes sense in functions declarations and variables initialization in c++ :

e_smth var;
var=99;

Will produce -fpermissive error if compiled with g++.

Both types with or without tag could be used as one file #define macro without parameters.


update

could be used as one file #define macro without parameters

meant : Instead of writing #define MAX 1000 in file and adding MAX to global use enum { MAX=1000 } just in file scope


And what about anonymous enums, I've found just one use cases: definition like typedef enum { a,b,c } some_t; makes it work like enum with tag

Question:

if I haven't yet described all reasonable use cases, what for anonymous enums should be used?

2r2w
  • 1,384
  • 1
  • 12
  • 29
  • 1
    IF I recall correctly, and I'm not sure that I have this exactly, way back in the day you had to use typedef with enum's, or else use the "enum" keyword when declaring variables of the enum type. Once you've got the typedef in place, putting a tag on the enum is irrelevant, so we didn't bother. So, tl;dr: Ancient history stuff. – mjfgates Apr 14 '12 at 20:51
  • > use the "enum" keyword when declaring variables It's old good C syntax but I've corrected question because it makes no sense here @mjfgates – 2r2w Apr 14 '12 at 20:56

4 Answers4

20

In C (but not in C++), enum can be [ab]used to define int constants.

For example, given this declaration:

const int MAX = 1024;

MAX is not a constant expression, it's the name of a read-only object. That means you can't use it in a case label, as the size of an array declared at file scope or with static, or in any other context requiring a constant expression.

But if you write:

enum { MAX = 1024 };

then MAX is a constant expression of type int, usable in any context where you could use the constant 1024.

Of course you could also write:

#define MAX 1024

but there are disadvantages to using the preprocessor: the identifier isn't scoped the way it would be given an ordinary declaration, for example.

The drawback is that such a constant can only be of type int.

C++ has different rules; enumeration constants are of the enumerated type, not int, but you can use declared constant objects as constant expressions (as long as the initializer is a constant expression).

To address the original question, when you use an enum declaration to create constants like this, there's no point in having either a tag or a typedef, since you'll never use the type itself.

Background: This:

enum foo { zero, one, two };
enum foo obj = two;

creates a type enum foo and constants zero, one, and two. In C, the constants are always of type int, which is admittedly odd, and the initialization of obj involves an implicit conversion from int to enum foo.

In C++, the type enum foo can also be referred to as just foo, and the constants are of type enum foo (which is compatible with some integer type, not necessarily int).

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • 3
    Another (cornercase) advantage of `enum` constants over `#defines` is that they can be defined inside a macro expansion. – Jens Gustedt Apr 14 '12 at 21:38
6

Another use case is as an element of a struct or union, typically when it doesn't make sense to use it by itself (because it's there solely to satisfy the ABI of a communication protocol or etc. and there is a more appropriate representation for programmatic use).

geekosaur
  • 59,309
  • 11
  • 123
  • 114
0

@eith Thompson

Your answer has the statement that "const int MAX = 1024; MAX is not a constant expression,". However, the example from the link http://en.cppreference.com/w/cpp/language/constant_expression shows that it's a constant expression and can be used in a array declaration. Constant expressions C++ C++ language Expressions Defines an expression that can be evaluated at compile time.

Such expressions can be used as non-type template arguments, array sizes, and in other contexts that require constant expressions, e.g.

int n = 1;
std::array<int, n> a1; // error, n is not a constant expression
const int cn = 2;
std::array<int, cn> a2; // OK, cn is a constant expression
robin
  • 1
0

Usually, you only need to name an enum when you use it more than once. In other words, if you define multiple variables using the same enum, then you need to name the enum. However, if you only use the enum once and there will only ever be one variable having that enum, then an anonymous enum makes sense. For example:

enum color { red, blue, gray, green };
enum color car_color;
enum color house_color;

Here there are multiple variables, so the enum is named.

typedef struct {
    int year;
    enum { Jan, Feb, Mar, Apr, May, Jun, July, Aug, Sep, Oct, Nov, Dec } month;
    unsigned int day;
} date;

Here the author plans to only use the enum once, so a name is unnecessary.

Tyler Durden
  • 11,156
  • 9
  • 64
  • 126