5

I've heard before that I should simply let the compiler choose which values to assign for enumerated constants if I'm not doing something clever like using the values as bitmasks. If I'm just using enumeration values for more explicit code documentation, are there any gotchas that could creep in if I don't explicitly define all the values? I believe that values are assigned in ascending order. Should I define the 1st value to ensure the same values for each successive compilation?

Joel B
  • 12,082
  • 10
  • 61
  • 69

2 Answers2

7

From C99, Section 6.7.2.2p3:

The identifiers in an enumerator list are declared as constants that have type int and may appear wherever such are permitted. An enumerator with = defines its enumeration constant as the value of the constant expression. If the first enumerator has no =, the value of its enumeration constant is 0. Each subsequent enumerator with no = defines its enumeration constant as the value of the constant expression obtained by adding 1 to the value of the previous enumeration constant. (The use of enumerators with = may produce enumeration constants with values that duplicate other values in the same enumeration.)

The only time you need to assign a value to the first enumerator is if you want its value to be different from 0. Usually, you wouldn't do that, since the enumerators are often used to index an array.

Below is a simple example of "adding 1 to the value of the previous".

enum {
  A,
  B,
  C = 0,
  D,
  E
};

int main ()
{
    printf("%d\n", A);
    printf("%d\n", B);
    printf("%d\n", C);
    printf("%d\n", D);
    printf("%d\n", E);
    return 0;
}

The output for the above program is:

0
1
0
1
2

The only "gotcha" that I can think of is that if you want multiple enum names to represent the same value, you should remember to either stick them right next to the item you alias, or at the bottom of the enum list. I prefer the latter so I can count the enum lines to predict what the enum values will be.

enum {
    A,
    B,
    E,

    /* aliases below */
    C = A,
    D = B
};

Otherwise, an enumerator is just like an int literal.

jxh
  • 69,070
  • 8
  • 110
  • 193
  • ok, but with your last phrase: no it is not a `const int`. It is not an object, has no address and is a compile time constant integer expression. – Jens Gustedt Jul 09 '12 at 16:24
  • @JensGustedt: `const int` came from the standard paragraph I quoted where it said "constants that have type `int`", but you are right that I misinterpreted it. I edited the sentence, regards – jxh Jul 09 '12 at 16:29
5

I think it will depend on your use of the type.

Advantages to not providing enum initializers:

  • Easier to add and remove values as you develop.
  • You won't accidentally define two identifiers with the same value.

Advantages to providing enum initializers:

  • Safe to serialize and deserialize the data. If you need to put these values in a file, network socket, etc., I would go ahead and write the values. (?)
  • Easier to look the values up for debugging purposes.
aschepler
  • 70,891
  • 9
  • 107
  • 161
  • How exactly is adding explicit values making it "Safe to serialize and deserialize the data"? If you use the same header between endpoints (i.e. read/write of a file, network client/server etc.) these constants are guaranteed to be exactly the same, whether they are defined explicitly or not. – ja2142 Apr 11 '22 at 07:55
  • @ja2142 I'm not really sure what I meant by that. Maybe I was thinking of the unspecified and implementation-defined aspects of enumerations, but yeah, that changes only types, not values. – aschepler Apr 11 '22 at 12:32