Enumeraciones (Informática)

Enumeraciones (Informática)
Información sobre la plantilla
Concepto:Son un tipo especial de variables que tienen la propiedad de que su rango de valores es un conjunto de constantes enteras denominadas constantes de enumeración, a cada una de las cuales se le asigna un valor

Enumeraciones (Informática). Las variables enumeradas, enumeraciones o más abreviadamente enum (palabra reservada), son un tipo especial de variables que tienen la propiedad de que su rango de valores es un conjunto de constantes enteras denominadas constantes de enumeración, a cada una de las cuales se le asigna un valor. Para mayor legibilidad del código estos valores del rango se identifican por nemónicos.

Ejemplo

Por ejemplo, la declaración:

enum dia { DOM, LUN, MART, MIER, JUEV, VIER, SAB } diaX;

Establece un tipo enum al que se identifica por dia. Las variables de este tipo pueden adoptar un conjunto de seis valores enteros 0, 1, 2, 3, 4, 5, 6 (enumeradores) representados por los nemónicos DOM, LUN,...,SAB. Además se define una variable diaX de este tipo (variable enumerada).

En el ejemplo anterior, la variable diaX puede adoptar siete valores enteros (del 0 al 6). El programa los identifica con los nemónicos ya señalados. Ojo: no confundir la variable -enumeración- con los valores que puede adoptar -constante de enumeración.

Cada enumeración distinta constituye un tipo de enumerando diferente.

Ejemplo:

enum Calificacion {APTO, NO-APTO}  c1;
enum Evolucion {SUBE, BAJA, IGUAL} c2; 

c1 y c2 son objetos de tipo distinto.

Puede omitirse la palabra clave enum si dia no es identificador de nada más en el mismo ámbito. El compilador sabe que se trata de una variable tipo enum por la sintaxis de la propia declaración. Por ejemplo, es correcto:

dia { DOM, LUN, MART, MIER, JUEV, VIER, SAB } diaX; 

El identificador dia es la etiqueta opcional del tipo, y puede ser usada en subsecuentes declaraciones de variables del mismo tipo:

enum Dia laborable, festivo;    // declara dos nuevas variables 

aunque también se podría omitir el especificador enum (el compilador ya sabe que Dia es de tipo enum):

Dia laborable, festivo;         // equivalente al anterior 

Como ocurre con las declaraciones de estructuras y uniones, si no existen otras variables del mismo tipo, puede omitirse la etiqueta con lo que tenemos un tipo anónimo:

enum { DOM, LUN, MART, MIER, JUEV, VIER, SAB } diaX;

También aquí (como ocurre con las estructuras y uniones), el inconveniente de declarar un tipo anónimo es que después no podemos volver a declarar otra variable del mismo tipo. Observe que las expresiones que siguen no son equivalentes!!

enum diaX { DOM, LUN, MART, MIER, JUEV, VIER, SAB };
enum { DOM, LUN, MART, MIER, JUEV, VIER, SAB } diaX; 

En C, una variable enumerada puede recibir cualquier valor de tipo int sin que se realice ninguna otra comprobación; en cambio C++ es más fuertemente tipado en este sentido, y a una variable enumerada solo se le puede asignar uno de sus enumeradores. Ejemplo:

diaX = LUN;       // Ok.
diaX = 1;         // Ilegal, a pesar que LUN == 1 

Las enumeraciones proporcionan un modo muy flexible de asociar nombres con valores, algo que también puede hacerse con los #define, sin embargo, las enumeraciones (aún de un solo elemento) presentan ventajas entre las que podemos señalar: Los valores pueden ser auto-generados Las variables de enumeradas ofrecen la posibilidad de comprobación. El depurador puede ser capaz de imprimir los valores de los enumeradores en su forma simbólica (lo que facilita grandemente las comprobaciones). En la práctica, las enumeraciones proporcionan un lugar ("placeholder") muy conveniente para almacenar constantes enteras como códigos de error o de cualquier otro tipo que podamos manejar en nuestras aplicaciones. Por ejemplo: en lugar de utilizar

 #define ERROR_NO_ERROR    0    
 #define ERROR_NOT_FOUND   1
 #define ERROR_BUSY        2
 #define ERROR_FULL        3
 ...

Es más conveniente utilizar un enumerador:

enum ERRORS { NO_ERROR, NOT_FOUND, BUSY, FULL, ... } err; 

Los tipos enum pueden aparecer en cualquier sitio donde sea permitido un entero. Ejemplo:

enum dias { LUN, MAR, MIER, JUEV, VIER, SAB, DOM } diaX;
enum dias diapago;
typedef enum dias DIAS;
DIAS *diaptr;
int i = MIER;
diaX = LUN;          // Ok.
*diaptr = diaX;      // Ok.
LUN = MIER;          // ILEGAL: LUN es una constante! 

Visibilidad

Las etiquetas de los enum comparten el mismo espacio de nombres que los de estructuras y uniones. Los identificadores de los enumeradores comparten el mismo espacio que los identificadores de las variables ordinarias; de aquí se deduce que los nombres de los enumeradores de las distintas enumeraciones, tienen que ser diferentes (los valores no tienen porqué serlo ni aún en la misma enumeración).

Ejemplo

int dom = 11;
{
   enum dias { dom, lun, mar, mier, juev, vier, sab } diaX;
   /* el enumerador dom oculta otra declaracion de int dom */
   struct dias { int i, j;};   // ILEGAL: identificador dias ya usado
   double mar;                 // ILEGAL: redefinicion de mar
}
dom = 12;                      // int dom vuelve a ser visible 

Asignaciones a tipo enum

En el compilador Borland C++ 5.5, las reglas para expresiones que contengan tipos enum pueden forzarse a ser más estrictas activando el conmutador -A (que significa ANSI C++ estricto), con lo que el compilador refuerza las reglas con mensajes de error. Así, al asignar un entero a una variable enum (como en el ejemplo) produciría un error.

enum color { Rojo, Verde, Azul };
 int f() {
   color c;
   c = 0;    // Incorrecto: a 'c' solo se le puede asignar Rojo, Verde o Azul
   return c;
 }

En estos casos de compilación estricta, se obtiene también un error cuando se pasa un entero como parámetro a una función que espera un enum o viceversa. Estudie el ejemplo propuesto teniendo en cuenta que el resultado de la expresión flag1|flag2 (OR inclusivo entre bits) es un entero.

En estos casos de compilación estricta, se obtiene también un error cuando se pasa un entero como parámetro a una función que espera un enum o viceversa. Estudie el ejemplo propuesto teniendo en cuenta que el resultado de la expresión flag1 | flag2 (OR inclusivo entre bits) es un entero.

#include <iostream.h>
enum En { flag1 = 0x01, flag2 = 0x02 };
int f1(En) {                 // L.3:
  return (flag1 + 1);
}
void f2() {
  int x = f1(flag1|flag2);   // L.7:
  cout << "El valor es: " << x << endl;
}
int main () {
  f2();
  return 0;
}

Aquí En es un tipo enum; los enumeradores flag1 y flag2 son constantes de enumeración de valores 1 y 2 respectivamente, que han definidas en formato hexadecimal. Al intentar compilar se produce un error: Cannot convert 'int' to 'En' in function f2() ya que la invocación a f1 en L7 espera un enum tipo En (como indica el prototipo de L3), pero se le pasa un int, ya que como se ha apuntado, la expresión flag1|flag2 produce un entero. Para arreglarlo, aplicamos un modelado de tipo al argumento pasado a la invocación en L.7, que lo transforma en el tipo exigido, con lo que la compilación se realiza sin novedad.

#include <iostream.h>
enum En { flag1 = 0x01, flag2 = 0x02 };
int f1(En) {                       // L.3:
  return (flag1 + 1);
}
void f2() {
  int x = f1(En (flag1|flag2) );   // L.7bis:
  cout << "El valor es: " << x << endl;
}
int main () {
  f2();
}
Salida:
El valor es: 2


Véase también

Fuente