Não tenho certeza de qual é a sintaxe adequada para o uso de enumerações C. Eu tenho o seguinte código:
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;
Mas isso não é compilado, com o seguinte erro:
error: conflicting types for ‘strategy’
error: previous declaration of ‘strategy’ was here
O que estou fazendo de errado?
strategy
como tendo um tipo enumerado anônimo e atribui a ele um dos valores declarados desse tipo. Além disso, se eu envolver o código apresentado em umamain()
função trivial , ele será compilado para mim, mesmo sem aviso, com o gcc 4.4.7. Algumas das respostas sugerem o mesmo, embora não em tantas palavras.strategy = IMMEDIATE;
como uma declaração. Ele tem uma forma que seria legal no pré-ANSI C, mas no moderno C é ilegal. As atribuições não são permitidas no escopo do arquivo.enum strategy { ... };
define um tipo enumerado chamadoenum strategy
, ondestrategy
está a tag.enum { ... } strategy;
define um tipo enumerado anônimo (sem tag) e um único objeto desse tipo chamadostrategy
. Ambos são perfeitamente legais; eles apenas significam coisas diferentes.Respostas:
A declaração de uma variável enum é feita assim:
No entanto, você pode usar a
typedef
para encurtar as declarações de variáveis, assim:Ter uma convenção de nomenclatura para distinguir entre tipos e variáveis é uma boa idéia:
fonte
enum MyEnum {} myVar;
e, em seguida, usar a variávelmyVar
da seguinte maneira:myVar = SOMEENUMCONSTANT;
Vale ressaltar que você não precisa de um
typedef
. Você pode fazer isso da seguinte maneiraÉ uma questão de estilo, se você prefere
typedef
. Sem ele, se você quiser se referir ao tipo de enumeração, precisará usarenum strategy
. Com isso, você pode apenas dizerstrategy
.Ambas as formas têm seus prós e contras. O primeiro é mais prolixo, mas mantém os identificadores de tipo no namespace da tag, onde eles não entram em conflito com os identificadores comuns (pense
struct stat
e astat
função: eles também não entram em conflito) e você vê imediatamente que é um tipo. O outro é mais curto, mas traz identificadores de tipo para o espaço para nome comum.fonte
enum
palavra-chave nas duas linhas.enum strategy { RANDOM, IMMEDIATE, SEARCH };
então, quando você deseja uma instância dessa enum: `enum strategy myEnum;Você está tentando declarar
strategy
duas vezes e é por isso que está recebendo o erro acima. O seguinte funciona sem nenhuma reclamação (compilada comgcc -ansi -pendantic -Wall
):Se, em vez do acima, a segunda linha foi alterada para:
A partir dos avisos, você pode ver facilmente seu erro:
Então o compilador levou
strategy = IMMEDIATE
solicitou uma declaração de uma variável chamadastrategy
com o tipo padrãoint
, mas já havia uma declaração anterior de uma variável com esse nome.No entanto, se você colocasse a atribuição na
main()
função, seria um código válido:fonte
Quando voce diz
você cria uma variável de instância única, chamada 'estratégia' de uma enumer sem nome. Isso não é uma coisa muito útil a se fazer - você precisa de um typedef:
fonte
Como está escrito, não há nada de errado com o seu código. Tem certeza de que não fez algo como
Para quais linhas as mensagens de erro apontam? Quando diz que "a declaração anterior de 'estratégia' estava aqui", o que está "aqui" e o que mostra?
fonte
strategy = IMMEDIATE;
no escopo do arquivo. Uma atribuição não pode acontecer no escopo do arquivo fora de todas as funções. Portanto, o compilador tentou tirar o melhor proveito do erro e assumiu o que ele queria dizerint strategy = IMMEDIATE;
, quando o conflito ocorreu.@ThoAppelsin em seu comentário à pergunta postada está certo. O trecho de código postado na pergunta é válido e sem erros. O erro que você tem deve ser devido a outra sintaxe incorreta em qualquer outro local do seu arquivo de origem c.
enum{a,b,c};
define três constantes simbólicas (a
,b
ec
) que são números inteiros com valores0
,1
e2
, respectivamente, mas quando usamosenum
é porque nós normalmente não se preocupam com o valor inteiro específico, que se preocupam mais com o significado do nome constante simbólica. Isso significa que você pode ter isso:e isso será exibido
1
.Isso também será válido:
e produzirá o mesmo de antes.
Se você fizer isto:
você terá um erro, mas se você fizer isso:
você não terá nenhum erro.
você consegue fazer isso:
e
aa
será uma variável inteira com valor0
. mas você também pode fazer isso:e terá o mesmo efeito (ou seja,
aa
sendo umint
com0
valor).você também pode fazer isso:
e
aa
seráint
com valor7
.porque você não pode repetir a definição constante simbólica com o uso de
enum
, como já disse anteriormente, você deve usar tags se desejar declararint
vars com o uso deenum
:o uso
typedef
disso é para evitar que você escreva todas as vezesenum tag1
para definir variáveis. Comtypedef
você, basta digitarTag1
:Você também pode ter:
A última coisa a dizer é que, como estamos falando de constantes simbólicas definidas, é melhor usar letras maiúsculas ao usar
enum
, ou seja, por exemplo:ao invés de
fonte
Vale ressaltar que em C ++ você pode usar "enum" para definir um novo tipo sem precisar de uma instrução typedef.
Acho essa abordagem muito mais amigável.
[editar - status C ++ esclarecido - eu tinha isso originalmente e depois o removi!]
fonte
typedef
ou especificar tambémenum
na declaração de variável: enum Strategy {RANDOM, IMMEDIATE, SEARCH}; ... enum Strategy myStrategy = IMMEDIATE;enum Strategy
. Eu fiz isso, veja abaixo.Parece haver uma confusão sobre a declaração.
Quando
strategy
vier antes,{RANDOM, IMMEDIATE, SEARCH}
como a seguir,você está criando um novo tipo chamado
enum strategy
. No entanto, ao declarar a variável, você precisa usar-enum strategy
se. Você não pode simplesmente usarstrategy
. Portanto, o seguinte é inválido.Embora, o seguinte seja válido
Quando
strategy
vem depois{RANDOM, IMMEDIATE, SEARCH}
, você está criando uma enumeração anônima e declarandostrategy
ser uma variável desse tipo.Então agora você pode fazer algo como
No entanto, você não pode declarar nenhuma outra variável do tipo
enum {RANDOM, IMMEDIATE, SEARCH}
porque nunca o nomeou. Portanto, o seguinte é inválidoVocê pode combinar as duas definições também
Typedef
como observado anteriormente, é usado para criar uma declaração de variável mais curta.Agora você disse ao compilador que
enum {RANDOM, IMMEDIATE, SEARCH}
é sinônimo destrategy
. Então agora você pode usar livrementestrategy
como tipo de variável. Você não precisaenum strategy
mais digitar . O seguinte é válido agoraVocê também pode combinar Typedef junto com o nome do enum para obter
Não há muita vantagem em usar esse método, além do fato de que agora você pode usá
strategy
-lo de formaenum strategyName
intercambiável.fonte
typedef enum strategy {RANDOM, IMMEDIATE, SEARCH} strategy
outypedef enum strategy {RANDOM, IMMEDIATE, SEARCH} strategy_type
. Isso tem alguma vantagemtypedef enum {RANDOM, IMMEDIATE, SEARCH} strategy
? Você pensaria em adicioná-los à sua resposta, para completar?Se você declarar o nome para enumeração, nenhum erro ocorrerá.
Se não declarado, você deve usar um
typedef
:Não exibirá um erro ...
fonte
Minha construção favorita e única usada sempre foi:
Eu acredito que isso irá remover o seu problema que você tem. Usar novo tipo é do meu ponto de vista a opção correta.
fonte
A resposta de Tarc é a melhor.
Grande parte da discussão enum é um arenque vermelho.
Compare este trecho de código: -
que dá
com este que compila sem nenhum problema.
A variável
strategy
precisa ser definida na declaração ou dentro de uma função etc. Você não pode escrever software arbitrário - atribuições em particular - no escopo global.O fato de ele ter usado enum {RANDOM, IMEDIATE, PESQUISA} em vez de int é relevante apenas na medida em que confunde pessoas que não podem ver além dele. As mensagens de erro de redefinição na pergunta mostram que foi isso que o autor fez de errado.
Portanto, agora você deve ver por que o primeiro exemplo abaixo está errado e os outros três estão bem.
Exemplo 1. ERRADO!
Exemplo 2. DIREITO.
Exemplo 3. DIREITO.
Exemplo 4. DIREITO.
Se você tiver um programa em funcionamento, poderá colar esses trechos no seu programa e ver que alguns são compilados e outros não.
fonte
Eu tentei com o gcc e, por ser necessário, fui forçado a usar a última alternativa, a compilar sem erros.
typedef enum estado {a = 0, b = 1, c = 2} estado ;
fonte
new
é uma má escolha de identificadores na família C porque é um operador em C ++.C
Declaração que atua como uma definição provisória de um número inteiro assinado
s
com tipo completo e declaração que atua como uma definição provisória de um número inteiro assinadoq
com tipo incompleto no escopo (que resolve para o tipo completo no escopo porque a definição de tipo está presente em qualquer lugar do escopo) (como qualquer definição provisória, os identificadoresq
es
podem ser redeclarados com a versão incompleta ou completa do mesmo tipoint
ouenum stuff
várias vezes, mas definidos apenas uma vez no escopo, por exemplo, int q = 3; e só podem ser redefinidos em um sub-escopo, e apenas utilizável após a definição). Além disso, você só pode usar o tipo completo deenum stuff
uma vez no escopo porque ele atua como uma definição de tipo.Uma definição de tipo de enumeração do compilador
enum stuff
também é apresentada no escopo do arquivo (utilizável antes e abaixo), bem como uma declaração de tipo encaminhamento (o tipoenum stuff
pode ter várias declarações, mas apenas uma definição / conclusão no escopo e pode ser redefinido em um sub-escopo) . Ele também atua como uma diretiva de compilador para substituira
com rvalue0
,b
por-4
,c
com5
,d
com-2
,e
com-3
,f
com-1
eg
com-2
no escopo atual. As constantes de enumeração agora se aplicam após a definição até a próxima redefinição em uma enumeração diferente que não pode estar no mesmo nível de escopo.O espaço de nome da tag compartilhado por enum, struct e union é separado e deve ser prefixado pelo tipo keyword (enum, struct ou union) em C, ou seja
enum a {a} b
, depois ,enum a c
deve ser usado e nãoa c
. Como o espaço para nome da tag é separado do espaço para nome do identificador,enum a {a} b
é permitido, masenum a {a, b} b
não porque as constantes estão no mesmo espaço para nome dos identificadores da variável, o espaço para nome do identificador.typedef enum a {a,b} b
também não é permitido porque typedef-names fazem parte do espaço para nome do identificador.O tipo de
enum bool
e as constantes seguem o seguinte padrão em C:Isso compila bem em C:
C ++
Em C ++, enumerações podem ter um tipo
Nessa situação, as constantes e o identificador têm o mesmo tipo, bool e um erro ocorrerá se um número não puder ser representado por esse tipo. Talvez = 2, o que não é um bool. Além disso, True, False e Bool não podem estar em minúsculas, caso contrário, entrarão em conflito com as palavras-chave do idioma. Um enum também não pode ter um tipo de ponteiro.
As regras para enumerações são diferentes em C ++.
Variáveis de enumerações em C ++ não são mais apenas números inteiros não assinados etc., elas também são do tipo enumeração e só podem ser atribuídas constantes na enumeração. No entanto, isso pode ser descartado.
Classes Enum
enum struct
é idêntico aenum class
O operador de resolução do escopo ainda pode ser usado para enumerações sem escopo.
Mas como w não pode ser definido como outra coisa no escopo, não há diferença entre
::w
e::a::w
fonte