Is the last comma in C enum required?
Asked Answered
J

12

27

Is the last comma required in a C enum declaration?

That is, is the comma after Val3 required?

enum { Val1, Val2, Val3, } someEnum;

Are there any side-effects of leaving it in/out?

Jagannath answered 27/4, 2009 at 9:6 Comment(1)
In standard C89, that last comma was explicitly prohibited. In C99, they allow it. The side-effect of leaving it in is that it can't be compiled by strict C89 compilers.Stockton
F
45

It's not required. Section 6.7.2.2 of C99 lists the syntax as:

enum-specifier:
    enum identifieropt { enumerator-list }
    enum identifieropt { enumerator-list , }
    enum identifier
enumerator-list:
    enumerator
    enumerator-list , enumerator
enumerator:
    enumeration-constant
    enumeration-constant = constant-expression

Notice the first two forms of enum-specifier, one with the trailing comma and one without.

One advantage I've seen to using it is in things like:

enum {
    Val1,
    Val2,
    Val3,
} someEnum;

where, if you want to add in (for example) Val4 and Val5, you just copy and paste the Val3 line without having to worry about adjusting commas.

It can also be to simplify automated code generators so that they don't have to have special handling for the final value. They can just output every value followed by a comma.

This can be likened to the oft-seen SQL:

select fld1, fld2 from tbl where 1=1 and fld1 > 8

In that case, the where 1=1 is there only so that you don't have to put a where before your first clause and an and before each subsequent one. You can just rely on the fact that the where is already there and just use and for all the ones you add.

Some people may think this reeks of laziness and they're right, but that's not necessarily a bad thing :-)

Any decent DBMS query optimiser should be able to strip out constant clause like that before going to the database tables.

Fridge answered 27/4, 2009 at 9:9 Comment(0)
H
16

Like everyone else says, the comma is not required. But it's new in C99 (wasn't allowed in C89) and will be allowed in the next version of C++ too.

One other rationale is to make a difference between a "length" enumerator and a normal enumerator:

enum Items {
    A,
    B,
    C,
    LENGTH
};

Now, you can put into your coding guideline that the last item in your enumeration should have a comma applied, but not if it is a "Length" item - which just tells how many items there are.

It also helps for automatic generation of items (using macros/preprocessors) like other answers explain.

Horst answered 27/4, 2009 at 12:21 Comment(1)
It's a shame that the LENGTH idiom breaks automatic checking for the completeness of switch(enum).Hepner
S
10

In standard C89, the last comma is not permitted. Full stop.

It was a common extension to allow it; in particular, it was supported by GCC, but the standard expressly disallowed it.

In standard C99, the last comma is allowed, for symmetry with array and structure initializers, which always did allow the trailing comma on the last item.

6.7.2.2 Enumeration specifiers

Syntax

   enum-specifier:
            enum identifieropt { enumerator-list }
            enum identifieropt { enumerator-list , }
            enum identifier

The primary advantage of permitting trailing commas is that it permits easier machine generation of (C source) code - you do not have to write special case code for the last (or, maybe, the first) item in the list of initializers. Hence, programs like Yacc and Lex, to name but two, can be slightly simpler.

Stockton answered 27/4, 2009 at 12:32 Comment(0)
L
5

The trailing , in an enum definition or array initializer is optional, but quite useful, especially in lists spanning multiple lines. It is allowed since C99 for reasons of symmetry as it gives all lines the same structure for each item:

enum DAY {
    MON = 1,
    TUE,
    WED,
    THU,
    FRI,
    SAT,
    SUN,
};

It makes it easier to generate array contents with scripts and avoids error prone situations where adding extra elements to an array but forgetting to add a comma might go unnoticed:

const char *osnames[] = {
    "CP/M",
    "MS/DOS",
    "Windows"
}

Adding extra items:

const char *osnames[] = {
    "CP/M",
    "MS/DOS",
    "Windows"
    "Linux",
    "OS/X"
};

Notice the missing comma in the middle of the list: the compiler parses the third string as "WindowsLinux" and the bug does not generate a syntax error.

With the trailing , on each line, it is much easier to add and delete items without modifying other lines. It is even more useful if lines are compiled conditionally as in this example:

const char *osnames[] = {
    "CP/M",
    "MS/DOS",
    "Windows",
#ifdef __UNIX__
    "Linux",
    "OS/X",
#endif
};
Leslie answered 4/8, 2018 at 16:20 Comment(0)
M
4

No it's not required. The reason being, it makes it easier for the purposes of cut and paste code, if you don't need to worry about whether the comma is meant to be there or not.

Monoicous answered 27/4, 2009 at 9:10 Comment(0)
H
3

No it is not required - in fact I would say having it there is bad style.

Hallucinatory answered 27/4, 2009 at 9:8 Comment(0)
B
3

As already stated it is not required. The reason that a trailing comma is supported is that it (assuming the items are laid out one to a line) it allows you to conveniently rearrange the order of items in an enumeration using cut/paste or drag/drop, and it also allows you to comment out the last item without producing a syntax error. Omitting the trailing comma is legal but loses these code maintenance advantages.

I'd forgotten but Nick is quite right. I too have exploited the trailing comma with compiler directives. Without it, the conditional code would have been a lot messier and harder to read.

Baggott answered 27/4, 2009 at 9:13 Comment(0)
T
3

It's optional and useful, if say you use macro, e.g.

#ifdef _FLAG
    #define OPTS opt_four, opt_five,
#else
    #define OPTS // none
#endif
enum {
  opt_one,
  opt_two,
  opt_three,
  OPTS
};
Thanet answered 27/4, 2009 at 9:17 Comment(0)
Y
2

The last trailing comma is not required.

I prefer trailing commas for two reasons:

  1. Clean git diffs.
  2. Easy editing in editors with line-based commands (e.g. Vim's dd).
Yacketyyak answered 6/11, 2016 at 19:10 Comment(0)
I
1

Other answers mention it but I'd just like to highlight that the trailing comma is disallowed in standards-conforming C89 and C++, which makes it a portability issue with old or uncommon compilers. Here's a useful link that explains this and many other C/C++ issues: http://david.tribble.com/text/cdiffs.htm#C99-enum-decl

Irredentist answered 29/12, 2009 at 7:35 Comment(0)
T
0

No, it's not required and should be omitted for code clarity. Its presence/absence has no effect.

Tribunate answered 27/4, 2009 at 9:7 Comment(2)
It would be considerably more precise to say that a trailing comma has no semantic value. Its absence can make code maintenance less convenient. In what way does the absence of a trailing comma make the code clearer?Baggott
When the last element of the enum is followed by a brace immediately it looks clearer to me. It's subjective I suppose.Tribunate
C
0

Its not required, infact some compilers complain if you add one. for instance Visual Studio 6.
One use for the comma is for creating enums using c macros.

#define ELEMENT(x) x,

enum MyElements {
  ELEMENT(a)
  ELEMENT(b)
  ELEMENT(c)
};

This pattern is useful if you there are several things you need to do with the elements and only want to define them once. For a more complete example of this you can look at the code of the libiconv and the iconv utility.

Channa answered 27/4, 2009 at 9:24 Comment(2)
This is bad. Why not use: "#define ELEMENT(x) x" and then add the commas in the enum?Subversion
The idea is that the contents of the enum are themselves another macro: #define ALL_ELEMENTS(ELEMENT) ELEMENT(a) ELEMENT(b) ELEMENT(c). You then #define ELEMENT to whatever you need at any particular time, and then invoke the ALL_ELEMENTS macro.Strahan

© 2022 - 2024 — McMap. All rights reserved.