Нет ли проблем с использованием перечисления без объявления переменной enum в C? - PullRequest
3 голосов
/ 26 мая 2020

Меня смущает, как именно переменная типа enum и переменная типа int работают по-разному в C.

Я слышал, что в C ++ может быть ошибка приведения между типом enum и целочисленным типом, но C не делает.

Тогда, если нет разницы между целочисленной переменной и переменной типа перечисления в C, могу ли я просто объявить имена перечислений и использовать их, не объявляя какие-либо переменные этого типа перечисления, например ,

 ...

 enum { WIN, LOSE, DRAW };

 int main() {

     int result;

     result = play_game(...);

     if (result == WIN) { ... }
     else if (result == LOSE) { ... }
     ...

 }

 int play_game(...) {
     ...
     if (...)       return WIN;
     else if (...)  return LOSE;
     else           return DRAW;
     ...
 }

как указано выше. (просто для повышения читабельности вместо использования бессмысленных чисел; 0, 1, 2, 10, -1, и c.)

Собственно, я не мог понять, что означает объявление переменной типа specifici c enum, как показано ниже.

 enum GameResult { WIN, LOSE, DRAW } result;

Связано ли это также с удобочитаемостью кода? Я имею в виду, есть ли разница между объявлением result как int и как переменной типа enum?

Ответы [ 3 ]

4 голосов
/ 26 мая 2020

Да, перечисления в основном заменяют int. Однако есть некоторые проблемы с передовым опытом в отношении опубликованного вами кода. Вопрос на грани субъективности, хотя является широко признанным хорошей практикой, позволяющей избегать "магических c чисел" в программировании C.

То есть вам не следует писать функцию, которая возвращает int со значением 0, 1 или 2. Это был бы довольно шифрованный c интерфейс. Но замена этих «магических c чисел» на enum без изменения типа возврата - это небрежно. Он не должен возвращать int, но вместо этого вы должны использовать typedef, например:

typedef enum { WIN, LOSE, DRAW } game_result_t;
...
game_result_t play_game(...)

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

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

// game.h

typedef enum { GAME_WIN, GAME_LOSE, GAME_DRAW } game_result_t;
...
game_result_t game_play (...)

Теперь все в game.h имеет префикс game_, что позволяет легко узнать, откуда взялась определенная константа или функция, без необходимости копаться / искать в коде.

3 голосов
/ 26 мая 2020

Да, идентификаторы, объявленные в перечислении, могут использоваться как обычные int константы согласно C 2018 6.4.4.3 2: «Идентификатор, объявленный как константа перечисления, имеет тип int» и 6.7.2.2 3: «Идентификаторы в списке перечислителя объявлены как константы, которые имеют тип int и могут появляться везде, где это разрешено».

Я имею в виду, есть разница между объявлением result как int и as Переменная типа перечисления?

Хотя константы перечисления имеют тип int, объект перечисления (переменная) может иметь другой целочисленный тип. То, что он имеет, определяется реализацией согласно 6.7.2.2 4.

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

0 голосов
/ 26 мая 2020

Да, перечисления используются для удобства чтения довольно часто. По умолчанию в перечислении первое значение равно 0. И они действительно похожи на массивы const.

 enum GameResult { WIN, LOSE, DRAW } result;

Я не рекомендую использовать это, так как неясно, будет ли результат 8-битный, 16-битный или какой-то другой. другое значение и когда это приведет к переполнению.

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