Подтвердить что ты не робот

Разница между Enum и Define Statement

В чем разница между использованием инструкции define и оператора перечисления в C/С++ (и есть ли разница при использовании их с C или С++)?

Например, когда следует использовать

enum {BUFFER = 1234}; 

над

#define BUFFER 1234   
4b9b3361

Ответ 1

enum определяет синтаксический элемент.

#define является пред-препроцессорной директивой, выполняемой до того, как компилятор видит код и, следовательно, не является элементом языка самого C.

В общем случае перечисления предпочтительнее, поскольку они являются безопасными по типу и более легко обнаруживаются. Определения сложнее найти и могут иметь сложное поведение, например, один фрагмент кода может переопределить #define, сделанный другим. Это может быть трудно отследить.

Ответ 2

Операторы

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

Перечисления являются частью самого языка C и имеют следующие преимущества.

1/Они могут иметь тип и компилятор может их проверить.

2/Поскольку они доступны компилятору, информация о символах на них может быть передана в отладчик, что облегчает отладку.

Ответ 3

Определить - это команда препроцессора, это просто как "заменить все" в вашем редакторе, он может заменить строку другим, а затем скомпилировать результат.

Enum - это особый случай типа, например, если вы пишете:

enum ERROR_TYPES
{
   REGULAR_ERR =1,
   OK =0
}

существует новый тип, называемый ERROR_TYPES. Верно, что REGULAR_ERR дает значение 1, но приведение из этого типа в int должно вызвать предупреждение о кастинге (если вы настроите свой компилятор на высокую многословность).

Резюме: они одинаковы, но при использовании перечисления вы получаете доступ к проверке типа и используя определения, вы просто заменяете строки кода.

Ответ 4

Перечисления обычно предпочтительнее, чем #define, где имеет смысл использовать перечисление:

  • Отладчики могут показать вам символическое имя значения enum ( "openType: OpenExisting", а не "openType: 2"
  • Вы получаете немного больше защиты от конфликтов имен, но это не так плохо, как было (большинство компиляторов предупреждают об re #define ition.

Самое большое отличие состоит в том, что вы можете использовать перечисления как типы:

// Yeah, dumb example
enum OpenType {
    OpenExisting,
    OpenOrCreate,
    Truncate
};

void OpenFile(const char* filename, OpenType openType, int bufferSize);

Это дает вам проверку типов параметров (вы не можете легко смешивать openType и bufferSize) и позволяет легко находить, какие значения действительны, что делает ваши интерфейсы намного проще в использовании. Некоторые IDE могут даже дать вам завершение кода intellisense!

Ответ 5

Всегда лучше использовать перечисление, если это возможно. Использование перечисления дает компилятору больше информации о вашем исходном коде, определение препроцессора никогда не рассматривается компилятором и, следовательно, несет меньше информации.

Для реализации, например, куча режимов, используя перечисление, позволяет компилятору, например, поймать отсутствующие case -статы в коммутаторе.

Ответ 6

enum может группировать несколько элементов в одну категорию:

enum fruits{ apple=1234, orange=12345};

а #define может создавать только несвязанные константы:

#define apple 1234
#define orange 12345

Ответ 7

#define - команда препроцессора, перечисление - на языке C или С++.

Всегда лучше использовать перечисления для #define для таких случаев. Одна вещь - безопасность типа. Другим является то, что, когда у вас есть последовательность значений, вам нужно только указать начало последовательности в перечислении, другие значения получат последовательные значения.

enum {
  ONE = 1,
  TWO,
  THREE,
  FOUR
};

вместо

#define ONE 1
#define TWO 2
#define THREE 3
#define FOUR 4

В качестве побочной заметки все же есть некоторые случаи, когда вам может понадобиться использовать #define (как правило, для некоторых макросов, если вам нужно построить идентификатор, который содержит константу), но этот вид макро черная магия, и очень очень редко, чтобы быть способ пойти. Если вы идете на эти конечности, вам, вероятно, следует использовать шаблон С++ (но если вы застряли с C...).

Ответ 8

Если вам нужна только эта константа (скажем, для буферизации), я бы не использовал перечисление, а определял. Я бы использовал перечисления для таких вещей, как возвращаемые значения (что означало разные условия ошибки) и везде, где нам нужно различать разные "типы" или "случаи". В этом случае мы можем использовать перечисление для создания нового типа, который мы можем использовать в прототипах функций и т.д., А затем компилятор может проверить, лучше ли этот код.

Ответ 9

Помимо всего, что уже написано, один сказал, но не показан и интересен. Например.

enum action { DO_JUMP, DO_TURNL, DO_TURNR, DO_STOP };
//...
void do_action( enum action anAction, info_t x );

Рассмотрение действия как типа делает вещи более ясными. Используя define, вы бы написали

void do_action(int anAction, info_t x);

Ответ 10

Для интегральных значений констант я предпочитаю enum более #define. Кажется, нет никаких недостатков в использовании enum (дисконтирование минимального недостатка в немного более типизации), но у вас есть преимущество в том, что enum можно ограничить, а идентификаторы #define имеют глобальную область видимости, которая тромбирует все.

Использование #define обычно не является проблемой, но поскольку для enum нет недостатков, я иду с этим.

В С++ я обычно предпочитаю от enum до const int, хотя в С++ a const int можно использовать вместо значения буквального целого (в отличие от C), потому что enum переносится на C (который я все еще много работают).

Ответ 11

Если у вас есть группа констант (например, "Дни недели" ), перечисления будут предпочтительнее, потому что это показывает, что они сгруппированы; и, как сказал Джейсон, они безопасны по типу. Если это глобальная константа (например, номер версии), это больше, чем вы использовали бы #define for; хотя это является предметом большого обсуждения.

Ответ 12

В дополнение к хорошим пунктам, перечисленным выше, вы можете ограничить область перечислений классом, структурой или пространством имен. Лично мне нравится иметь минимальное количество релевантных символов в области видимости в любой момент, что является еще одной причиной использования перечислений, а не #defines.

Ответ 13

Еще одно преимущество перечисления над списком определений заключается в том, что компиляторы (по крайней мере, gcc) могут генерировать предупреждение, когда не все значения проверяются в инструкции switch. Например:

enum {
    STATE_ONE,
    STATE_TWO,
    STATE_THREE
};

...

switch (state) {
case STATE_ONE:
    handle_state_one();
    break;
case STATE_TWO:
    handle_state_two();
    break;
};

В предыдущем коде компилятор может генерировать предупреждение о том, что не все значения перечисления обрабатываются в коммутаторе. Если состояния были выполнены как # define, это не так.

Ответ 14

перечисления больше используются для перечисления какого-либо набора, например дней в неделю. Если вам нужно только одно постоянное число, const int (или double и т.д.) Будет определенно лучше, чем перечисление. Мне лично не нравится #define (по крайней мере, не для определения некоторых констант), потому что он не дает мне типа безопасности, но вы можете, конечно, использовать его, если он вам подходит.

Ответ 15

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

Кроме того, при использовании отладчика у вас есть доступ к значениям литералов перечисления. Это не всегда относится к #define.

Ответ 16

Enum:

1. Обычно используется для нескольких значений

2. В перечислении есть две вещи: одно имя, а другое - значение имени, которое должно быть выделено, но значение может быть одинаковым. Если мы не определяем значение, тогда первое значение имени перечисления равно 0 секунде 1 и т.д., Если явно не указано значение.

3. У них может быть тип и компилятор, который может набрать их.

4. Сделать отладку проще

5. Мы можем ограничить его объем до класса.

Определить:

1. Когда нам нужно определить только одно значение

2. Он обычно заменяет одну строку на другую. 3.. Область видимости глобальна, мы не можем ограничить ее область.

В целом мы должны использовать enum

Ответ 17

Есть небольшая разница. В стандарте C говорится, что перечисления имеют интегральный тип и что константы перечисления имеют тип int, поэтому оба могут свободно перемешаться с другими интегральными типами без ошибок. (Если, с другой стороны, такое смешение было запрещено без явных приемов, разумное использование перечислений могло бы поймать определенные ошибки программирования.)

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

Ответ 18

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

Например:

    #define OPT_X1 1 /* introduced in version 1 */
    #define OPT_X2 2 /* introduced in version  2 */

Затем программное обеспечение, которое может быть скомпилировано с любой версией, может выполнять

    #ifdef OPT_X2
    int flags = OPT_X2;
    #else
    int flags = 0;
    #endif

В то время как при перечислении это невозможно без механизма обнаружения функции времени выполнения.