No estoy seguro de cuál es la sintaxis adecuada para usar las enumeraciones C. Tengo el siguiente código:
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;
Pero esto no se compila, con el siguiente error:
error: conflicting types for ‘strategy’
error: previous declaration of ‘strategy’ was here
¿Qué estoy haciendo mal?
strategy
que tiene un tipo enumerado anónimo y le asigna uno de los valores declarados de ese tipo. Además, si envuelvo el código presentado en unamain()
función de otra manera trivial , entonces me compila bien, sin siquiera una advertencia, con gcc 4.4.7. Algunas de las respuestas implican lo mismo, aunque no en muchas palabras.strategy = IMMEDIATE;
como una declaración. Tiene una forma que habría sido legal en C anterior a ANSI, pero en C moderna es ilegal. Las asignaciones no están permitidas en el alcance del archivo.enum strategy { ... };
define un tipo enumerado llamadoenum strategy
, dondestrategy
está la etiqueta.enum { ... } strategy;
define un tipo anónimo enumerado (sin etiqueta) y un único objeto de ese tipo llamadostrategy
. Ambos son perfectamente legales; solo significan cosas diferentes.Respuestas:
La declaración de una variable enum se hace así:
Sin embargo, puede usar a
typedef
para acortar las declaraciones de variables, así:Tener una convención de nomenclatura para distinguir entre tipos y variables es una buena idea:
fuente
enum MyEnum {} myVar;
y luego usar la variable de lamyVar
siguiente manera:myVar = SOMEENUMCONSTANT;
Vale la pena señalar que no necesita a
typedef
. Puedes hacerlo de la siguiente maneraEs una pregunta de estilo si lo prefieres
typedef
. Sin él, si desea hacer referencia al tipo de enumeración, debe usarloenum strategy
. Con eso, solo puedes decirstrategy
.Ambas formas tienen sus ventajas y desventajas. El uno es más prolijo, pero mantiene los identificadores de tipo en el espacio de nombre de etiqueta donde no entrarán en conflicto con los identificadores ordinarios (piense
struct stat
y lastat
función: tampoco entran en conflicto), y donde inmediatamente ve que es un tipo. El otro es más corto, pero trae identificadores de tipo al espacio de nombres ordinario.fuente
enum
palabra clave en ambas líneas.enum strategy { RANDOM, IMMEDIATE, SEARCH };
entonces cuando quieres una instancia de esa enumeración: `enum strategy myEnum;Estás tratando de declarar
strategy
dos veces, y es por eso que obtienes el error anterior. Lo siguiente funciona sin ninguna queja (compilado congcc -ansi -pendantic -Wall
):Si en lugar de lo anterior, la segunda línea se cambió a:
De las advertencias, puede ver fácilmente su error:
Entonces el compilador tomó
strategy = IMMEDIATE
una declaración de una variable llamadastrategy
con el tipo predeterminadoint
, pero ya había una declaración previa de una variable con este nombre.Sin embargo, si coloca la asignación en la
main()
función, sería un código válido:fuente
Cuando tu dices
crea una variable de instancia única, llamada 'estrategia' de una enumeración sin nombre. Esto no es algo muy útil, necesita un typedef:
fuente
Como está escrito, no hay nada malo con su código. ¿Estás seguro de que no has hecho algo como
¿A qué líneas apuntan los mensajes de error? Cuando dice "la declaración previa de 'estrategia' estaba aquí", ¿qué es "aquí" y qué muestra?
fuente
strategy = IMMEDIATE;
en el ámbito del archivo. Una asignación no puede suceder en el ámbito del archivo fuera de todas las funciones. Entonces el compilador trató de sacar el máximo provecho del error y asumió que se refería a élint strategy = IMMEDIATE;
, momento en el cual ocurrió el conflicto.@ThoAppelsin en su comentario a la pregunta publicada es correcto. El fragmento de código publicado en la pregunta es válido y no contiene errores. El error que tiene debe deberse a otra sintaxis incorrecta en cualquier otro lugar de su archivo fuente c.
enum{a,b,c};
define tres constantes simbólicas (a
,b
yc
) que son números enteros con valores0
,1
y2
respectivamente, pero cuando lo usamosenum
es porque generalmente no nos importa el valor entero específico, nos importa más el significado del nombre simbólico constante. Esto significa que puedes tener esto:y esto dará salida
1
.Esto también será válido:
y producirá lo mismo que antes.
Si haces esto:
tendrá un error, pero si hace esto:
No tendrás ningún error.
Puedes hacerlo:
y
aa
será una variable entera con valor0
. pero también puedes hacer esto:y tendrá el mismo efecto (es decir,
aa
ser unaint
con0
valor).También puedes hacer esto:
y
aa
seráint
con valor7
.porque no puede repetir la definición simbólica constante con el uso de
enum
, como he dicho anteriormente, debe usar etiquetas si desea declararint
vars con el uso deenum
:su uso
typedef
es para evitar que escriba cada vezenum tag1
que defina variables. Contypedef
usted solo puede escribirTag1
:También puedes tener:
Lo último que hay que decir es que, dado que estamos hablando de constantes simbólicas definidas, es mejor usar letras mayúsculas cuando se usan
enum
, es decir, por ejemplo:en vez de
fuente
Vale la pena mencionar que en C ++ puede usar "enum" para definir un nuevo tipo sin necesidad de una declaración typedef.
Este enfoque me parece mucho más amigable.
[editar - aclarado el estado de C ++ - ¡Tenía esto originalmente, luego lo eliminé!]
fuente
typedef
o especificar tambiénenum
en la declaración de variables: enum Strategy {RANDOM, INMEDIATE, SEARCH}; ... enumeración Estrategia myStrategy = INMEDIATO;enum Strategy
. Lo hice, ver más abajo.Parece haber una confusión sobre la declaración.
Cuando
strategy
viene antes{RANDOM, IMMEDIATE, SEARCH}
como en el siguiente,Estás creando un nuevo tipo llamado
enum strategy
. Sin embargo, al declarar la variable, debe usarlaenum strategy
. No puedes simplemente usarstrategy
. Entonces lo siguiente no es válido.Mientras, lo siguiente es válido
Cuando
strategy
viene después{RANDOM, IMMEDIATE, SEARCH}
, está creando una enumeración anónima y luego declarastrategy
ser una variable de ese tipo.Ahora puedes hacer algo como
Sin embargo, no puede declarar ninguna otra variable de tipo
enum {RANDOM, IMMEDIATE, SEARCH}
porque nunca la ha nombrado. Entonces lo siguiente no es válidoPuedes combinar ambas definiciones también
Typedef
como se señaló anteriormente, se utiliza para crear una declaración de variable más corta.Ahora le ha dicho al compilador que
enum {RANDOM, IMMEDIATE, SEARCH}
es sinónimo destrategy
. Así que ahora puedes usarlo librementestrategy
como tipo variable. No necesitas escribirenum strategy
más. Lo siguiente es válido ahoraTambién puede combinar Typedef junto con el nombre de enumeración para obtener
No hay mucha ventaja de utilizar este método, aparte del hecho de que ahora se puede utilizar
strategy
yenum strategyName
de manera intercambiable.fuente
typedef enum strategy {RANDOM, IMMEDIATE, SEARCH} strategy
otypedef enum strategy {RANDOM, IMMEDIATE, SEARCH} strategy_type
. ¿Tiene eso alguna ventajatypedef enum {RANDOM, IMMEDIATE, SEARCH} strategy
? ¿Consideraría agregar estos a su respuesta, para completar?Si declara el nombre para la enumeración, no se producirá ningún error.
Si no se declara, debe usar un
typedef
:No mostrará un error ...
fuente
Mi construcción favorita y solo usada siempre fue:
Creo que esto eliminará el problema que tienes. Usar un nuevo tipo es, desde mi punto de vista, la opción correcta.
fuente
La respuesta de Tarc es la mejor.
Gran parte de la discusión sobre la enumeración es un arenque rojo.
Compare este fragmento de código: -
lo que da
con este que se compila sin problemas.
La variable
strategy
debe establecerse en la declaración o dentro de una función, etc. No puede escribir software arbitrario, asignaciones en particular, en el ámbito global.El hecho de que haya usado enum {RANDOM, INMEDIATE, SEARCH} en lugar de int solo es relevante en la medida en que ha confundido a las personas que no pueden ver más allá. Los mensajes de error de redefinición en la pregunta muestran que esto es lo que el autor ha hecho mal.
Entonces, ahora debería poder ver por qué el primero del ejemplo a continuación está mal y los otros tres están bien.
Ejemplo 1. ¡Incorrecto!
Ejemplo 2. DERECHO.
Ejemplo 3. DERECHO.
Ejemplo 4. DERECHO.
Si tiene un programa en funcionamiento, debería poder pegar estos fragmentos en su programa y ver que algunos compilan y otros no.
fuente
Intenté con gcc y pensé en mi necesidad. Me vi obligado a usar la última alternativa, para compilar sin errores.
typedef enum state {a = 0, b = 1, c = 2} estado ;
fuente
new
es una mala elección de identificadores en la familia C porque es un operador en C ++.C
Declaración que actúa como una definición tentativa de un número entero
s
con signo con tipo completo y declaración que actúa como una definición tentativa de número enteroq
con signo con tipo incompleto en el ámbito (que resuelve el tipo completo en el ámbito porque la definición de tipo está presente en cualquier lugar del alcance) (como cualquier definición tentativa, los identificadoresq
y ses
pueden volver a declarar con la versión incompleta o completa del mismo tipoint
oenum stuff
varias veces, pero solo se definen una vez en el alcance, es decir, int q = 3; y solo se pueden redefinir en un subscopio, y solo utilizable después de la definición). Además, solo puede usar el tipo completo deenum stuff
una vez en el ámbito porque actúa como una definición de tipo.Una definición de tipo de enumeración del compilador
enum stuff
también se hace presente en el alcance del archivo (utilizable antes y a continuación), así como una declaración de tipo de reenvío (el tipoenum stuff
puede tener múltiples declaraciones pero solo una definición / finalización en el alcance y puede redefinirse en un subscopio) . También actúa como directiva compiladora para sustituira
con rvalue0
,b
with-4
,c
with5
,d
with-2
,e
with-3
,f
with-1
yg
with-2
en el ámbito actual. Las constantes de enumeración ahora se aplican después de la definición hasta la próxima redefinición en una enumeración diferente que no puede estar en el mismo nivel de alcance.El espacio de nombres de etiqueta compartido por enum, struct y union está separado y debe tener el prefijo de la palabra clave type (enum, struct o union) en C, es decir
enum a {a} b
, despuésenum a c
debe usarse y noa c
. Debido a que el espacio de nombres de la etiqueta está separado del espacio de nombres del identificador,enum a {a} b
está permitido peroenum a {a, b} b
no porque las constantes estén en el mismo espacio de nombres que los identificadores variables, el espacio de nombres del identificador.typedef enum a {a,b} b
tampoco está permitido porque typedef-names son parte del espacio de nombres del identificador.El tipo de
enum bool
y las constantes siguen el siguiente patrón en C:Esto compila bien en C:
C ++
En C ++, las enumeraciones pueden tener un tipo
En esta situación, las constantes y el identificador tienen el mismo tipo, bool, y se producirá un error si un número no puede ser representado por ese tipo. Quizás = 2, que no es un bool. Además, Verdadero, Falso y Bool no pueden ser minúsculas, de lo contrario chocarán con las palabras clave del idioma. Una enumeración tampoco puede tener un tipo de puntero.
Las reglas para las enumeraciones son diferentes en C ++.
Las variables de enumeración en C ++ ya no son solo enteros sin signo, etc., también son de tipo enumeración y solo se les pueden asignar constantes en la enumeración. Sin embargo, esto puede descartarse.
Clases de enumeración
enum struct
es idéntico aenum class
El operador de resolución de alcance todavía se puede usar para enumeraciones sin ámbito.
Pero debido a que w no puede definirse como algo más en el alcance, no hay diferencia entre
::w
y::a::w
fuente