Namespaces
Variants

Enumerations

From cppreference.net

Un tipo enumerado es un tipo distinto cuyo valor es un valor de su tipo subyacente (ver más abajo), que incluye los valores de constantes nombradas explícitamente ( constantes de enumeración ).

Contenidos

Sintaxis

El tipo enumerado se declara utilizando el siguiente especificador de enumeración como el type-specifier en la gramática de declaración :

enum attr-spec-seq  (opcional) identifier  (opcional) { enumerator-list } (1)
enum attr-spec-seq  (opcional) identifier  (opcional) : type { enumerator-list } (2) (desde C23)
1) Declara una enumeración sin un tipo subyacente fijo.
2) Declara una enumeración de tipo subyacente fijo type .

donde enumerator-list es una lista separada por comas (se permite coma final) (desde C99) de enumerator , cada uno de los cuales tiene la forma:

enumeration-constant attr-spec-seq  (opcional) (1)
enumeration-constant attr-spec-seq  (opcional) = constant-expression (2)

donde

identifier , enumeration-constant - identificadores introducidos por esta declaración
constant-expression - expresión constante entera cuyo valor es representable como un valor de tipo int (hasta C23) . Si la enumeración tiene un tipo subyacente fijo, representable como un valor de type (desde C23)
attr-spec-seq - (C23) lista opcional de atributos ,
  • aplicados a toda la enumeración si aparece después de enum ,
  • aplicados al enumerator si aparece después de enumeration-constant

Al igual que con struct o union , una declaración que introduce un tipo enumerado y una o más constantes de enumeración también puede declarar uno o más objetos de ese tipo o de un tipo derivado del mismo.

enum color { RED, GREEN, BLUE } c = RED, *cp = &c;
// introduce el tipo enum color
// las constantes enteras RED, GREEN, BLUE
// el objeto c de tipo enum color
// el objeto cp de tipo puntero a enum color

Explicación

Cada constante-de-enumeración que aparece en el cuerpo de un especificador de enumeración se convierte en una constante entera con tipo int (hasta C23) en el ámbito circundante y puede utilizarse siempre que se requieran constantes enteras (por ejemplo, como etiqueta de caso o como tamaño de arreglo no VLA).

Durante el procesamiento de cada constante de enumeración en la lista de enumeradores, el tipo de la constante de enumeración será:

  • el tipo previamente declarado, si es una redeclaración de la misma constante de enumeración; o,
  • el tipo enumerado, para una enumeración con tipo subyacente fijo; o,
  • int , si no hay constantes de enumeración previas en la lista de enumeradores y no hay un = explícito con una expresión constante entera definitoria; o,
  • int , si se proporciona explícitamente con = y el valor de la expresión constante entera es representable por un int; o,
  • el tipo de la expresión constante entera, si se proporciona explícitamente con = y si el valor de la expresión constante entera no es representable por int ; o,
  • el tipo del valor de la última constante de enumeración con 1 añadido. Si dicha expresión constante entera desbordara o envolvería el valor de la constante de enumeración previa por la adición de 1, el tipo adopta:
    • un tipo entero con signo de tamaño adecuado (excluyendo los tipos enteros con signo de precisión de bits) capaz de representar el valor de la constante de enumeración previa más 1; o,
    • un tipo entero sin signo de tamaño adecuado (excluyendo los tipos enteros sin signo de precisión de bits) capaz de representar el valor de la constante de enumeración previa más 1.

Se elige un tipo entero con signo si la constante de enumeración previa que se está sumando es de tipo entero con signo. Se elige un tipo entero sin signo si la constante de enumeración previa es de tipo entero sin signo. Si no existe un tipo entero de tamaño adecuado descrito previamente que pueda representar el nuevo valor, entonces la enumeración no tiene ningún tipo capaz de representar todos sus valores.

(desde C23)
enum color { RED, GREEN, BLUE } r = RED;
switch(r)
{
case RED:
    puts("rojo");
    break;
case GREEN:
    puts("verde");
    break;
case BLUE:
    puts("azul");
    break;
}

Si enumeration-constant está seguido por = constant-expression , su valor es el valor de esa expresión constante. Si enumeration-constant no está seguido por = constant-expression , su valor es uno mayor que el valor del enumerador anterior en la misma enumeración. El valor del primer enumerador (si no utiliza = constant-expression ) es cero.

enum Foo { A, B, C = 10, D, E = 1, F, G = F + C };
// A=0, B=1, C=10, D=11, E=1, F=2, G=12

El identificador mismo, si se utiliza, se convierte en el nombre del tipo enumerado en el espacio de nombres de etiquetas y requiere el uso de la palabra clave enum (a menos que se defina mediante typedef en el espacio de nombres ordinario).

enum color { RED, GREEN, BLUE };
enum color r = RED; // OK
// color x = GREEN; // Error: color is not in ordinary name space
typedef enum color color_t;
color_t x = GREEN; // OK

Cada tipo enumerado sin un tipo subyacente fijo (since C23) es compatible con uno de: char , un tipo entero con signo, o un tipo entero sin signo (excluyendo bool y los tipos enteros de precisión de bits) (since C23) . Está definido por la implementación qué tipo es compatible con cualquier tipo enumerado dado, pero cualquiera que sea, debe ser capaz de representar todos los valores de enumerador de esa enumeración. Para todas las enumeraciones con un tipo subyacente fijo, el tipo enumerado es compatible con el tipo subyacente de la enumeración. (since C23)

El tipo de miembro de enumeración para un tipo enumerado sin tipo subyacente fijo al completarse es:

  • int si todos los valores de la enumeración son representables como un int ; o,
  • el tipo enumerado.
(desde C23)
Todas las enumeraciones tienen un tipo subyacente. El tipo subyacente puede especificarse explícitamente usando un especificador-de-tipo-enum y es su tipo subyacente fijo. Si no se especifica explícitamente, el tipo subyacente es el tipo compatible de la enumeración, que es un tipo entero con signo o sin signo, o char . (desde C23)

Los tipos enumerados son tipos enteros, y como tales pueden utilizarse en cualquier lugar donde se puedan usar otros tipos enteros, incluyendo en conversiones implícitas y operadores aritméticos .

enum { ONE = 1, TWO } e;
long n = ONE; // promoción
double d = ONE; // conversión
e = 1.2; // conversión, e es ahora ONE
e = e + 1; // e es ahora TWO

Notas

A diferencia de struct o union , no existen enums declarados por adelantado en C:

enum Color; // Error: no forward-declarations for enums in C
enum Color { RED, GREEN, BLUE };

Las enumeraciones permiten la declaración de constantes con nombre de una manera más conveniente y estructurada que #define ; son visibles en el depurador, obedecen las reglas de ámbito y participan en el sistema de tipos.

#define TEN 10
struct S { int x : TEN; }; // CORRECTO

o

enum { TEN = 10 };
struct S { int x : TEN; }; // también correcto

Desde C23 constexpr puede utilizarse para el mismo propósito:

constexpr int TEN = 10;
struct S { int x : TEN; }; // también correcto

Además, como una struct o una union no establece su ámbito en C, un tipo de enumeración y sus constantes de enumeración pueden introducirse en la especificación de miembros de la primera, y su ámbito es el mismo que el de la primera, posteriormente.

struct Element
{
    int z;
    enum State { SOLID, LIQUID, GAS, PLASMA } state;
} oxygen = { 8, GAS };
// el tipo enum State y sus constantes de enumeración permanecen visibles aquí, ej.
void foo(void)
{
    enum State e = LIQUID; // OK
    printf("%d %d %d ", e, oxygen.state, PLASMA); // imprime 1 2 3
}

Ejemplo

#include <stdio.h>
int main(void)
{
    enum TV { FOX = 11, CNN = 25, ESPN = 15, HBO = 22, MAX = 30, NBC = 32 };
    printf("List of cable stations:\n");
    printf(" FOX: \t%2d\n", FOX);
    printf(" HBO: \t%2d\n", HBO);
    printf(" MAX: \t%2d\n", MAX);
}

Salida:

List of cable stations:
 FOX:   11
 HBO:   22
 MAX:   30

Referencias

  • Estándar C23 (ISO/IEC 9899:2024):
  • 6.2.5/21 Tipos (p: 39)
  • 6.7.2.2 Especificadores de enumeración (p: 107-112)
  • Estándar C17 (ISO/IEC 9899:2018):
  • 6.2.5/16 Tipos (p: 32)
  • 6.7.2.2 Especificadores de enumeración (p: 84-85)
  • Estándar C11 (ISO/IEC 9899:2011):
  • 6.2.5/16 Tipos (p: 41)
  • 6.7.2.2 Especificadores de enumeración (p: 117-118)
  • Estándar C99 (ISO/IEC 9899:1999):
  • 6.2.5/16 Tipos (p: 35)
  • 6.7.2.2 Especificadores de enumeración (p: 105-106)
  • Estándar C89/C90 (ISO/IEC 9899:1990):
  • 3.1.2.5 Tipos
  • 3.5.2.2 Especificadores de enumeración

Palabras clave

enum

Véase también

Documentación de C++ para declaración de enumeración