Возможный дубликат:
Зачем использовать перечисление, когда #define так же эффективно?
При программировании на языке C лучше использовать #define-инструкции или перечисления для состояний в конечной машине?
Возможный дубликат:
Зачем использовать перечисление, когда #define так же эффективно?
При программировании на языке C лучше использовать #define-инструкции или перечисления для состояний в конечной машине?
Поскольку состояния являются связанными элементами, я думаю, что лучше иметь перечисление, определяющее их.
Технически это не имеет значения. Компилятор, скорее всего, даже создаст идентичный машинный код для любого случая, но перечисление имеет три преимущества:
Используя правую комбинацию компилятора + отладчика, отладчик будет печатать переменные перечисления по имени перечисления, а не по их числу. Итак, "StateBlahBlup" читает гораздо приятнее, чем "41", не так ли?
Вы явно не указываете каждому государству число, компилятор делает нумерацию для вас, если вы ее разрешите. Предположим, что у вас уже есть 20 состояний, и вы хотите добавить новое состояние посередине, в случае определений вам нужно все перенумеровать самостоятельно. В случае перечисления вы можете просто добавить состояние, и компилятор изменит нумерацию всех состояний ниже этого нового состояния.
Вы можете сообщить компилятору предупредить вас, если оператор switch не обрабатывает все возможные значения перечисления, например. потому что вы забыли обработать некоторые значения или потому, что перечисление было расширено, но вы забыли также обновить операторы switch, обрабатывающие значения enum (он не будет предупреждать, если есть случай default
, хотя все значения, которые не обрабатываются явно, заканчиваются по умолчанию случай).
Нет окончательного ответа. enum
предлагает вам определение масштаба и автоматического присвоения значений, но не дает никакого контроля над постоянным типом (всегда signed int
). #define
игнорирует область видимости, но позволяет использовать более удобные средства ввода текста: позволяет выбрать тип константы (либо с помощью суффиксов, либо путем включения явного приведения в определение).
Итак, выберите для себя, что для вас важнее. Для конечного автомата enum
может быть лучшим выбором, если у вас нет веских оснований для управления типом.
Я предпочитаю перечисление. Они более компактны и более безопасны. Вы также можете указать порядок в перечислении, который может быть полезен в конечной машине. #defines следует избегать, если это возможно, поскольку они будут перезаписывать все вхождения в источнике, что может привести к некоторым непреднамеренным действиям, которые трудно отлаживать.
#define
могут иметь множество непредвиденных последствий и не следовать общим правилам определения области. Используйте перечисления при наличии связанных данных.
Дополнительная информация: http://www.embedded.com/columns/programmingpointers/9900402?_requestid=341945 [материал С++, но все же незначительно релевантный]
Если enum
поддерживается вашим компилятором, это было бы предпочтительнее. В противном случае используйте #define
. Все компиляторы С++ и современные компиляторы C должны поддерживать enum
, но более старые компиляторы (в частности, предназначенные для встроенных платформ) могут не поддерживать enum
.
Если вы должны использовать #define
, обязательно определите свои константы в круглых скобках, чтобы избежать ошибок препроцессора:
#define RED_STATE (1)
#define YELLOW_STATE (2)
#define GREEN_STATE (3)
Вы можете сделать этот трюк, чтобы заставить компилятор проверить тип значения #define
.
#define VALUE_NAME ((TYPE_NAME) 12)
Однако реальная проблема #define
заключается в ее переопределении в коде приложения. (Конечно, компилятор предупредит вас об этом.)
enum
отлично работает, когда у вас есть эксклюзивные опции, но вы не можете использовать их для определения битовых полей, например:
#define SQ_DEFAULT 0x0
#define SQ_WITH_RED 0x1
#define SQ_WITH_BLUE 0x2
void paint_square(int flags);
Затем вы можете нарисовать красно-синий квадрат с помощью
paint_square(SQ_WITH_RED | SQ_WITH_BLUE);
... который вы не можете с помощью enum
.
Вы можете использовать все, что хотите и как.
Как все говорят, я также хотел бы добавить меня в качестве голосования за Enums.
Перечисления всегда должны быть предпочтительными, если вы используете связанные данные, как в случае машины состояния, вы также можете определить порядок в перечислениях, который поможет в реализации State Machine.
Далее перечисления сохранят вашу программу в безопасности, так как все перечисления будут иметь свой тип только для того, чтобы избежать возможных путаниц.
#define не следует использовать в случае конечного автомата или связанных данных. В любом случае, это мое предложение, но нет жесткого и быстрого правила.
Также я хотел бы добавить еще одно замечание о том, что перечисления добавят больше читабельности и понятности вашему коду, если они будут использоваться в будущем или, если они будут прочитаны кем-то другим. Это важный момент, когда у вас очень большая программа, и в программе есть много #defines, кроме того, что вы используете для своей государственной машины.