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?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Lehane
  • 47,588
  • 14
  • 53
  • 53
  • 12
    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. – Jonathan Leffler Dec 29 '09 at 07:31

12 Answers12

44

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.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
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.

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
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.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
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
};
chqrlie
  • 131,814
  • 10
  • 121
  • 189
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.

1800 INFORMATION
  • 131,367
  • 29
  • 160
  • 239
3

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

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.

Peter Wone
  • 17,965
  • 12
  • 82
  • 134
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
};
Nick
  • 27,566
  • 12
  • 60
  • 72
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).
skrulcik
  • 51
  • 4
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

Dan Olson
  • 22,849
  • 4
  • 42
  • 56
1

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

sharptooth
  • 167,383
  • 100
  • 513
  • 979
  • 3
    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? – Peter Wone Apr 27 '09 at 09:17
  • When the last element of the enum is followed by a brace immediately it looks clearer to me. It's subjective I suppose. – sharptooth Apr 27 '09 at 10:25
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.

shoosh
  • 76,898
  • 55
  • 205
  • 325
  • This is bad. Why not use: "#define ELEMENT(x) x" and then add the commas in the enum? – nilton Dec 06 '10 at 21:49
  • 1
    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. – Raymond Chen Dec 29 '11 at 01:23