Как определить перечисляемый тип (enum) в C?
Я не уверен, что такое правильный синтаксис для использования C-перечислений. У меня есть следующий код:
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;
Но это не скомпилируется со следующей ошибкой:
error: conflicting types for ‘strategy’
error: previous declaration of ‘strategy’ was here
Что я делаю неправильно?
Ответы
Ответ 1
Объявление переменной enum выполняется следующим образом:
enum strategy {RANDOM, IMMEDIATE, SEARCH};
enum strategy my_strategy = IMMEDIATE;
Однако вы можете использовать typedef
, чтобы сократить объявления переменных, например:
typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy my_strategy = IMMEDIATE;
Наличие соглашения об именах для различения типов и переменных является хорошей идеей:
typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy_type;
strategy_type my_strategy = IMMEDIATE;
Ответ 2
Стоит отметить, что вам не нужен typedef
. Вы можете просто сделать это следующим образом
enum strategy { RANDOM, IMMEDIATE, SEARCH };
enum strategy my_strategy = IMMEDIATE;
Это вопрос стиля, предпочитаете ли вы typedef
. Без него, если вы хотите обратиться к типу перечисления, вам нужно использовать enum strategy
. С его помощью вы можете просто сказать strategy
.
Оба способа имеют свои про и минусы. Один из них более многословен, но сохраняет идентификаторы типов в пространстве имен тегов, где они не будут конфликтовать с обычными идентификаторами (подумайте о struct stat
и функции stat
: они также не конфликтуют), и где вы сразу видите что это тип. Другой - короче, но привносит идентификаторы типов в обычное пространство имен.
Ответ 3
Вы пытаетесь объявить strategy
дважды, и почему вы получаете указанную выше ошибку. Следующие работы без каких-либо жалоб (скомпилированы с gcc -ansi -pendantic -Wall
):
#include <stdio.h>
enum { RANDOM, IMMEDIATE, SEARCH } strategy = IMMEDIATE;
int main(int argc, char** argv){
printf("strategy: %d\n", strategy);
return 0;
}
Если вместо вышесказанного вторая строка была изменена на:
...
enum { RANDOM, IMMEDIATE, SEARCH } strategy;
strategy = IMMEDIATE;
...
Из предупреждений вы можете легко увидеть свою ошибку:
enums.c:5:1: warning: data definition has no type or storage class [enabled by default]
enums.c:5:1: warning: type defaults to ‘int’ in declaration of ‘strategy’ [-Wimplicit-int]
enums.c:5:1: error: conflicting types for ‘strategy’
enums.c:4:36: note: previous declaration of ‘strategy’ was here
Таким образом, компилятор принял strategy = IMMEDIATE
для объявления переменной с именем strategy
с типом по умолчанию int
, но уже было объявление объявления с этим именем.
Однако, если вы поместили назначение в функцию main()
, это будет действительный код:
#include <stdio.h>
enum { RANDOM, IMMEDIATE, SEARCH } strategy = IMMEDIATE;
int main(int argc, char** argv){
strategy=SEARCH;
printf("strategy: %d\n", strategy);
return 0;
}
Ответ 4
Когда вы говорите
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
вы создаете одну переменную экземпляра, называемую "стратегией" безымянного перечисления. Это не очень полезная вещь - вам нужен typedef:
typedef enum {RANDOM, IMMEDIATE, SEARCH} StrategyType;
StrategyType strategy = IMMEDIATE;
Ответ 5
Как написано, в коде нет ничего плохого. Вы уверены, что не сделали что-то вроде
int strategy;
...
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
В каких строках указывают сообщения об ошибках? Когда он говорит, что "предыдущее объявление" стратегии "было здесь", что "здесь" и что оно показывает?
Ответ 6
@ThoAppelsin в своем комментарии к опубликованному вопросу прав. Фрагмент кода, отправленный в вопросе, действителен и без ошибок. Ошибка, которую вы имеете, должна быть связана с другим плохим синтаксисом в любом другом месте вашего исходного файла c. enum{a,b,c};
определяет три символьные константы (a
, b
и c
), которые являются целыми числами со значениями 0
, 1
и 2
соответственно, но когда мы используем enum
, это происходит потому, что мы надеваем Обычно меня интересует конкретное целочисленное значение, мы больше заботимся о значении символьного имени константы.
Это означает, что вы можете это сделать:
#include <stdio.h>
enum {a,b,c};
int main(){
printf("%d\n",b);
return 0;
}
и это выведет 1
.
Это также будет справедливо:
#include <stdio.h>
enum {a,b,c};
int bb=b;
int main(){
printf("%d\n",bb);
return 0;
}
и будет выводить то же, что и раньше.
Если вы это сделаете:
enum {a,b,c};
enum {a,b,c};
у вас будет ошибка, но если вы это сделаете:
enum alfa{a,b,c};
enum alfa;
у вас не будет никаких ошибок.
вы можете сделать это:
enum {a,b,c};
int aa=a;
и aa
будет целочисленной переменной со значением 0
. но вы также можете это сделать:
enum {a,b,c} aa= a;
и будет иметь тот же эффект (т.е. aa
является int
с 0
значением).
вы также можете сделать это:
enum {a,b,c} aa= a;
aa= 7;
и aa
будет int
со значением 7
.
потому что вы не можете повторить определение символической константы с использованием enum
, как я уже говорил ранее, вы должны использовать теги, если хотите объявить int
vars с помощью enum
:
enum tag1 {a,b,c};
enum tag1 var1= a;
enum tag1 var2= b;
использование typedef
позволяет безопасно записывать каждый раз enum tag1
для определения переменной. С помощью typedef
вы можете просто ввести Tag1
:
typedef enum {a,b,c} Tag1;
Tag1 var1= a;
Tag1 var2= b;
Вы также можете:
typedef enum tag1{a,b,c}Tag1;
Tag1 var1= a;
enum tag1 var2= b;
Последнее, что сказать, что, поскольку мы говорим об определенных символьных константах, лучше использовать заглавные буквы при использовании enum
, то есть, например:
enum {A,B,C};
вместо
enum {A,B,C};
Ответ 7
Стоит отметить, что в С++ вы можете использовать "enum" для определения нового типа без инструкции typedef.
enum Strategy {RANDOM, IMMEDIATE, SEARCH};
...
Strategy myStrategy = IMMEDIATE;
Я считаю этот подход более дружелюбным.
[edit - уточнил статус С++ - у меня это было изначально, а затем удалено!]
Ответ 8
Кажется, что есть замешательство в декларации.
Когда strategy
предшествует {RANDOM, IMMEDIATE, SEARCH}
, как показано ниже,
enum strategy {RANDOM, IMMEDIATE, SEARCH};
вы создаете новый тип с именем enum strategy
. Однако при объявлении переменной вам нужно использовать enum strategy
. Вы не можете просто использовать strategy
. Таким образом, следующее недопустимо.
enum strategy {RANDOM, IMMEDIATE, SEARCH};
strategy a;
В то время как справедливо следующее:
enum strategy {RANDOM, IMMEDIATE, SEARCH};
enum strategy queen = RANDOM;
enum strategy king = SEARCH;
enum strategy pawn[100];
Когда strategy
появляется после {RANDOM, IMMEDIATE, SEARCH}
, вы создаете анонимное перечисление, а затем объявляете strategy
переменной такого типа.
Итак, теперь вы можете сделать что-то вроде
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = RANDOM;
Однако вы не можете объявить какую-либо другую переменную типа enum {RANDOM, IMMEDIATE, SEARCH}
, потому что вы ее никогда не называли. Поэтому недопустимо следующее:
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
enum strategy a = RANDOM;
Вы также можете комбинировать оба определения
enum strategy {RANDOM, IMMEDIATE, SEARCH} a, b;
a = RANDOM;
b = SEARCH;
enum strategy c = IMMEDIATE;
Typedef
, как указано выше, используется для создания более короткого объявления переменной.
typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy;
Теперь вы сказали компилятору, что enum {RANDOM, IMMEDIATE, SEARCH}
является автономным с strategy
. Итак, теперь вы можете свободно использовать strategy
как тип переменной. Вам больше не нужно набирать enum strategy
. В настоящее время действует
strategy x = RANDOM;
Вы также можете комбинировать Typedef вместе с именем enum, чтобы получить
typedef enum strategyName {RANDOM, IMMEDIATE, SEARCH} strategy;
Не так много преимуществ использования этого метода, кроме того, что вы можете теперь использовать strategy
и enum strategyName
взаимозаменяемые.
typedef enum strategyName {RANDOM, IMMEDIATE, SEARCH} strategy;
enum strategyName a = RANDOM;
strategy b = SEARCH;
Ответ 9
Если вы объявите имя для перечисления, ошибка не будет.
Если не объявлено, вы должны использовать typedef
:
enum enum_name {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;
Не будет отображаться ошибка...
Ответ 10
Тарк ответ самый лучший.
Большая часть обсуждения enum - красная сельдь.
Сравните этот фрагмент кода: -
int strategy;
strategy = 1;
void some_function(void)
{
}
который дает
error C2501: 'strategy' : missing storage-class or type specifiers
error C2086: 'strategy' : redefinition
с этим, который компилируется без проблем.
int strategy;
void some_function(void)
{
strategy = 1;
}
strategy
переменных должна быть установлена при объявлении или внутри функции и т.д. Вы не можете писать произвольное программное обеспечение - в частности, назначения - в глобальной области видимости.
Тот факт, что он использовал enum {RANDOM, IMMEDIATE, SEARCH} вместо int, имеет отношение только к той степени, в которой он запутал людей, которые не могут видеть за его пределами. Сообщения об ошибках переопределения в вопросе показывают, что автор поступил неправильно.
Так что теперь вы должны понять, почему первый из приведенных ниже примеров неверен, а остальные три в порядке.
Пример 1. НЕПРАВИЛЬНО!
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;
void some_function(void)
{
}
Пример 2. ПРАВО.
enum {RANDOM, IMMEDIATE, SEARCH} strategy = IMMEDIATE;
void some_function(void)
{
}
Пример 3. ПРАВО.
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
void some_function(void)
{
strategy = IMMEDIATE;
}
Пример 4. ПРАВО.
void some_function(void)
{
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;
}
Если у вас есть работающая программа, вы можете просто вставить эти фрагменты в вашу программу и увидеть, что некоторые компилируются, а некоторые нет.
Ответ 11
Моя любимая и единственная использованная конструкция всегда была:
typedef enum MyBestEnum
{
/* good enough */
GOOD = 0,
/* even better */
BETTER,
/* divine */
BEST
};
Я верю, что это устранит вашу проблему.
Ответ 12
Я попытался с gcc и придумал для своей потребности, что мне пришлось использовать последнюю альтернативу, чтобы скомпилировать с ошибкой.
typedef enum state {a = 0, b = 1, c = 2} состояние;
typedef enum state {a = 0, b = 1, c = 2} state;
typedef enum state old; // New type, alias of the state type.
typedef enum state new; // New type, alias of the state type.
new now = a;
old before = b;
printf("State now = %d \n", now);
printf("Sate before = %d \n\n", before);