Требуется ли последняя запятая в C enum? - PullRequest
21 голосов
/ 27 апреля 2009

Требуется ли последняя запятая в объявлении C enum?

т.е. запятая после VAL3 обязательна?

enum { Val1, Val2, Val3, } someEnum;

Есть ли какие-либо побочные эффекты, если оставить его включенным / выключенным

Спасибо

Ответы [ 12 ]

36 голосов
/ 27 апреля 2009

Это не обязательно. В разделе 6.7.2.2 из C99 синтаксис представлен следующим образом:

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

Обратите внимание на первые две формы enum-specifier, одну с запятой и одну без.

Одно из преимуществ, которое я видел в его использовании, заключается в таких вещах, как:

enum {
    Val1,
    Val2,
    Val3,
} someEnum;

где, если вы хотите добавить (например) Val4 и Val5, просто скопируйте и вставьте строку Val3, не беспокоясь о настройке запятых.

И, как указано в комментарии, также может быть упрощено создание автоматических генераторов кода, чтобы им не требовалась специальная обработка окончательного значения. Они могут просто выводить каждое значение, за которым следует запятая.

Это можно сравнить с часто встречающимся SQL:

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

В этом случае where 1=1 существует только для того, чтобы вам не приходилось ставить where перед вашим первым предложением и and перед каждым последующим. Вы можете просто положиться на тот факт, что where уже есть и просто использовать and для всех добавленных вами.

Некоторые люди могут думать, что это пахнет ленью, и они правы, но это не обязательно плохо: -)

Любой приличный оптимизатор запросов к СУБД должен иметь возможность вырезать такое постоянное предложение перед тем, как перейти к таблицам базы данных.

15 голосов
/ 27 апреля 2009

Как все говорят, запятая не обязательна. Но это новое в C99 (не было разрешено в C89) и будет разрешено в следующей версии C ++.

Еще одно обоснование - провести различие между перечислителем "длины" и обычным перечислителем:

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

Теперь вы можете указать в своем руководстве по кодированию, что к последнему элементу в вашем перечислении должна быть применена запятая, но не если это элемент "Длина", который просто сообщает, сколько элементов существует.

Это также помогает для автоматической генерации элементов (с использованием макросов / препроцессоров), как объясняют другие ответы.

8 голосов
/ 27 апреля 2009

В стандарте C89 последняя запятая не допускается. Полная остановка.

Это было обычное расширение, позволяющее это делать; в частности, он был поддержан GCC, но стандарт явно запретил его.

В стандарте C99 допускается последняя запятая для симметрии с инициализаторами массива и структуры, которая всегда допускала запятую в последнем элементе.

6.7.2.2 Спецификаторы перечисления

Синтаксис

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

Основное преимущество разрешения конечных запятых состоит в том, что оно позволяет проще генерировать машинный код (исходный код на C) - вам не нужно писать код специального регистра для последнего (или, возможно, первого) элемента в списке инициализаторов , Следовательно, такие программы, как Yacc и Lex, если не считать двух, могут быть немного проще.

4 голосов
/ 27 апреля 2009

Нет, это не обязательно. Причина в том, что это упрощает процесс вырезания и вставки кода, если вам не нужно беспокоиться о том, будет ли запятая или нет.

3 голосов
/ 27 апреля 2009

Как уже говорилось, это не обязательно. Причина, по которой поддерживается запятая, заключается в том, что она (при условии, что элементы располагаются по одной в строке) позволяет удобно упорядочивать порядок элементов в перечислении с помощью операций вырезания / вставки или перетаскивания, а также позволяет закомментировать последний элемент без синтаксической ошибки. Пропуск запятой через запятую законен, но теряет эти преимущества обслуживания кода.

Я забыл, но Ник совершенно прав. Я тоже использовал запятую с директивами компилятора. Без него условный код был бы намного сложнее и сложнее для чтения.

3 голосов
/ 27 апреля 2009

Нет, это не требуется - на самом деле я бы сказал, что это плохой стиль.

2 голосов
/ 27 апреля 2009

Это необязательно и полезно, если, скажем, вы используете макрос, например

#ifdef _FLAG
    #define OPTS opt_four, opt_five,
#else
    #define OPTS // none
#endif
enum {
  opt_one,
  opt_two,
  opt_three,
  OPTS
};
1 голос
/ 06 ноября 2016

Последняя запятая не обязательна.

Я предпочитаю конечные запятые по двум причинам:

  1. Clean git diffs .
  2. Простое редактирование в редакторах с помощью строчных команд (например, Vim's dd).
0 голосов
/ 04 августа 2018

Конечный , в определении enum или инициализаторе массива необязателен, но весьма полезен, особенно в списках, охватывающих несколько строк. Это разрешено начиная с C99 по соображениям симметрии, поскольку все линии имеют одинаковую структуру для каждого элемента:

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

Это упрощает генерацию содержимого массива с помощью сценариев и позволяет избежать ситуаций, подверженных ошибкам, когда добавление дополнительных элементов в массив, но забвение добавления запятой может остаться незамеченным:

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

Добавление дополнительных предметов:

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

Обратите внимание на пропущенную запятую в середине списка: компилятор разбирает третью строку как "WindowsLinux", и ошибка не генерирует синтаксическую ошибку.

С завершающим , на каждой строке гораздо проще добавлять и удалять элементы без изменения других строк. Еще более полезно, если строки компилируются условно, как в этом примере:

const char *osnames[] = {
    "CP/M",
    "MS/DOS",
    "Windows",
#ifdef __UNIX__
    "Linux",
    "OS/X",
#endif
};
0 голосов
/ 29 декабря 2009

В других ответах упоминается об этом, но я просто хотел бы подчеркнуть, что конечная запятая запрещена в C89 и C ++, соответствующих стандартам, что делает ее проблемой переносимости со старыми или необычными компиляторами. Вот полезная ссылка, которая объясняет эту и многие другие проблемы C / C ++: http://david.tribble.com/text/cdiffs.htm#C99-enum-decl

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...