Должен ли я явно определять значения моих перечисляемых констант

Я уже слышал, что должен просто позволить компилятору выбирать, какие значения присваивать перечисляемым константам, если я не делаю чего-то умного, например, использую значения в качестве битовых масок. Если я просто использую значения перечисления для более подробной документации кода, есть ли какие-либо ошибки, которые могут возникнуть, если я не определю явно все значения? Я считаю, что значения присваиваются в порядке возрастания. Должен ли я определить 1-е значение, чтобы обеспечить одинаковые значения для каждой последующей компиляции?


person Joel B    schedule 09.07.2012    source источник


Ответы (2)


Я думаю, это будет зависеть от вашего использования типа.

Преимущества отсутствия инициализаторов enum:

  • Легче добавлять и удалять значения по мере разработки.
  • Вы не сможете случайно определить два идентификатора с одинаковым значением.

Преимущества предоставления инициализаторов enum:

  • Безопасно сериализовать и десериализовать данные. Если вам нужно поместить эти значения в файл, сетевой сокет и т. д., я бы пошел дальше и написал значения.
  • Легче искать значения для целей отладки.
person aschepler    schedule 09.07.2012

Из C99, раздел 6.7.2.2p3:

Идентификаторы в списке перечислителя объявляются как константы типа int и могут появляться везде, где это разрешено. Перечислитель со знаком = определяет свою константу перечисления как значение константного выражения. Если у первого перечислителя нет =, значение его константы перечисления равно 0. Каждый последующий перечислитель без = определяет свою константу перечисления как значение константного выражения, полученного путем прибавления 1 к значению предыдущей константы перечисления. (Использование перечислителей со знаком = может привести к созданию констант перечисления со значениями, дублирующими другие значения в том же перечислении.)

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

Ниже приведен простой пример «прибавления 1 к значению предыдущего».

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;
}

Вывод для вышеуказанной программы:

0
1
0
1
2

Единственный «подводный камень», о котором я могу думать, заключается в том, что если вы хотите, чтобы несколько имен enum представляли одно и то же значение, вы должны не забыть прикрепить их либо прямо рядом с элементом, который вы называете псевдонимом, либо внизу списка enum. Я предпочитаю последнее, поэтому я могу подсчитать enum строк, чтобы предсказать, какими будут значения enum.

enum {
    A,
    B,
    E,

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

В противном случае перечислитель похож на литерал int.

person jxh    schedule 09.07.2012
comment
хорошо, но с вашей последней фразой: нет, это не const int. Это не объект, не имеет адреса и представляет собой постоянное целочисленное выражение времени компиляции. - person Jens Gustedt; 09.07.2012
comment
@JensGustedt: const int взято из стандартного абзаца, который я процитировал, где говорится о константах, имеющих тип int, но вы правы, что я неправильно это истолковал. Я отредактировал предложение, с уважением - person jxh; 09.07.2012