Saltar al contenido

Enums y typedef

Enumeraciones con tipo subyacente fijo (novedad de C23), el arte de typedef para nombrar tipos, y los tipos opacos que ocultan implementación tras una API.

Nombrar bien los tipos es diseño, no cosmética. Los enums dan nombres a conjuntos de valores; typedef crea alias que aclaran la intención y habilitan la encapsulación. Con C23, los enums además ganan control sobre su representación en memoria.

  • Enums y su valor numérico.
  • Enums con tipo subyacente fijo (C23).
  • typedef para claridad y abstracción.
  • Tipos opacos: ocultar la implementación.

Enums

Un enum da nombres a constantes enteras relacionadas:

C
enum Estado {    INACTIVO,        // 0    CARGANDO,        // 1    LISTO,           // 2    ERROR = 10,      // puedes fijar valores    ABORTADO         // 11 (sigue desde el anterior)};enum Estado s = LISTO;

Usa enums en vez de “números mágicos” (if (s == 2)): if (s == LISTO) se lee solo y el compilador te ayuda con los switch exhaustivos.

Enums con tipo fijo (C23)

Antes, el tipo entero que respaldaba un enum lo elegía el compilador, lo que causaba problemas de tamaño y ABI. C23 te deja fijarlo:

C
enum Color : unsigned char {   // C23: respaldado por unsigned char (1 byte)    ROJO, VERDE, AZUL};

Por qué el tipo fijo importa en sistemas

Sin tipo fijo, el tamaño de un enum era impredecible entre compiladores y plataformas — un problema real cuando ese enum forma parte de un formato binario, un protocolo de red o una struct compartida entre módulos compilados por separado. Fijar : unsigned char o : uint32_t garantiza el tamaño y el layout exactos, haciendo el enum seguro para serializar y para cruzar fronteras de ABI (nivel 21). Es otro ejemplo del patrón de C23: darte control explícito donde antes había ambigüedad de implementación.

typedef: alias de tipos

typedef crea un nombre nuevo para un tipo existente. Dos usos principales:

C
// 1) claridad: nombres con significadotypedef uint32_t Id;typedef struct Punto Punto;      // usar 'Punto' en vez de 'struct Punto'// 2) simplificar tipos complejos (punteros a función)typedef int (*Operacion)(int, int);Operacion op = sumar;            // mucho más legible

typedef con moderación

typedef aclara, pero también puede ocultar. Un typedef sobre un puntero (typedef struct X *XPtr) esconde que hay una indirección, lo que confunde sobre la propiedad y la vida del objeto. La convención sensata: usa typedef para structs (evita repetir struct), para punteros a función (que son ilegibles sin él), y para tipos opacos (abajo); pero no escondas punteros normales tras un alias. Que el lector vea el * cuando lo hay.

Tipos opacos: encapsulación en C

El patrón más potente que habilita typedef: exponer un tipo en tu header sin revelar su contenido. El usuario recibe un puntero opaco y solo puede tocarlo a través de tu API.

C
// archivo.h (lo que ve el usuario)typedef struct Conexion Conexion;   // declaración adelantada, sin camposConexion *conexion_abrir(const char *host);void      conexion_cerrar(Conexion *c);int       conexion_enviar(Conexion *c, const char *msg);// archivo.c (privado)struct Conexion {                    // la definición real, oculta    int socket;    char buffer[4096];    // …};

El tipo opaco es la clase de C

Este patrón es cómo C logra encapsulación de verdad — el equivalente a los campos privados de una clase. El usuario de tu biblioteca recibe un Conexion * que puede pasar por ahí, pero no puede acceder a sus campos ni depende de su tamaño: solo existe tu API pública. Esto te da libertad total para cambiar la implementación (añadir campos, reorganizar) sin romper a nadie, y es la base de una ABI estable (nivel 21). FILE * de la librería estándar es exactamente esto: nunca has visto qué hay dentro de un FILE, y no lo necesitas. Diseñar tus módulos con tipos opacos es programación de sistemas madura.

Nombra y encapsula

  1. Define un enum de estados y úsalo en un switch (con -Wall para el chequeo exhaustivo).
  2. Crea un enum C23 con tipo subyacente fijo y comprueba su sizeof.
  3. Usa typedef para un puntero a función y simplifica una declaración.
  4. Diseña un tipo opaco: header con la API, .c con la struct oculta. El usuario nunca ve los campos.