Tipos fundamentales y novedades de C23
Los tipos de C, sus tamaños y trampas de signo, los enteros de ancho fijo, y las novedades de C23 que modernizan el lenguaje: auto, constexpr, nullptr, typeof y _BitInt.
En C, los tipos no son una formalidad: definen cuántos bytes ocupa un dato, cómo se interpreta y qué operaciones son seguras. Dominar el sistema de tipos —incluidas sus trampas históricas y las mejoras de C23— es la base de todo código correcto.
- Los tipos fundamentales y sus tamaños.
- Enteros de ancho fijo con
<stdint.h>. - Las trampas de signo y las promociones.
- Las novedades de C23:
auto,constexpr,nullptr,typeof,_BitInt.
Los tipos fundamentales
int entero = 42; // entero, al menos 16 bits (normalmente 32)
char letra = 'A'; // 1 byte; ¿con signo o sin? depende (¡trampa!)
float decimal = 3.14f; // coma flotante simple precisión
double preciso = 3.14159; // doble precisión (el habitual para decimales)
bool activo = true; // en C23, bool/true/false son palabras clave
Sorpresa clásica: el estándar C solo garantiza tamaños mínimos y relaciones (int ≥ 16 bits, long ≥ 32, sizeof(char) == 1). El tamaño real depende de la plataforma. Un int suele ser 32 bits hoy, pero confiar en ello es un bug esperando a ocurrir. Comprueba siempre con sizeof, e imprime con el especificador correcto.
#include <stdio.h>
printf("int: %zu bytes, long: %zu, void*: %zu\n",
sizeof(int), sizeof(long), sizeof(void *));
Enteros de ancho fijo
Cuando el tamaño debe ser exacto (protocolos, formatos binarios, hardware), usa <stdint.h>:
#include <stdint.h>
uint8_t byte = 255; // exactamente 8 bits, sin signo
int32_t con32 = -1000; // exactamente 32 bits, con signo
uint64_t grande = 1ULL << 40; // exactamente 64 bits
Para lógica de negocio, int está bien. Pero en programación de sistemas —donde manejas bytes, registros de hardware o formatos de red— usa uint8_t, int32_t, etc. Dejan la intención explícita y el tamaño garantizado en cualquier plataforma. Es la diferencia entre código que funciona “en mi máquina” y código portable de verdad.
La trampa del signo
Mezclar enteros con y sin signo es una fuente inagotable de bugs, porque C hace conversiones implícitas que no esperas:
unsigned int u = 1;
int s = -1;
if (s < u) printf("menor\n"); // ¡NO se imprime!
// -1 se convierte a un unsigned enorme; -1 > 1 en ese mundo
El compilador te avisa de esto con -Wextra (-Wsign-compare). Es otra razón para compilar siempre con avisos (nivel 2). Las promociones enteras las verás a fondo en el nivel 5.
Novedades de C23
C23 moderniza el sistema de tipos sin traicionar la filosofía de C:
auto — inferencia de tipos
auto x = 42; // int, inferido
auto y = 3.14; // double, inferido
Útil para no repetir tipos largos. No abuses: en C, tipos explícitos suelen comunicar mejor.
constexpr — constantes de compilación
constexpr int TAM = 256; // evaluado en compilación, con tipo
int buffer[TAM]; // válido como tamaño de array
Mejor que #define TAM 256 (que es texto sin tipo) y que un const int (que no siempre es una constante de compilación en C).
nullptr — el puntero nulo con tipo
int *p = nullptr; // en vez de NULL; tiene tipo nullptr_t, más seguro
nullptr evita las ambigüedades históricas de NULL (que a veces es 0, a veces (void*)0).
typeof — el tipo de una expresión
int a = 5;
typeof(a) b = 10; // b es int
typeof_unqual(a) c = 3; // como typeof pero quita const/volatile
Base para macros genéricas seguras (lo verás con _Generic, nivel 15).
_BitInt(N) — enteros de anchura exacta en bits
_BitInt(4) nibble = 7; // exactamente 4 bits, con signo
unsigned _BitInt(24) color; // 24 bits justos, para RGB por ejemplo
Control de anchura al bit, útil en hardware, compresión y aritmética precisa.
Fíjate en el patrón de todas estas novedades: cada una reemplaza un truco peligroso por algo seguro y con tipo. constexpr sustituye macros de constantes; nullptr sustituye el ambiguo NULL; typeof habilita macros genéricas sin hacks; _BitInt da precisión que antes requería manipulación manual de bits. C23 no te aleja del metal —sigues controlando cada byte— sino que te da herramientas más afiladas para hacerlo con menos riesgo. Adóptalas: es el C de siempre, mejor.
- Imprime
sizeofdeint,long,void*ylong doubleen tu máquina. - Reproduce la trampa del signo con
unsignedvsinty observa el aviso de-Wextra. - Declara constantes con
constexpry úsalas como tamaño de un array. - Usa
autoytypeofen un par de declaraciones. - Define un
_BitInt(N)y comprueba su rango con un desbordamiento a propósito.