C23: Un C ligeramente mejor
C23, la última revisión del estándar del lenguaje C, introduce un conjunto de funciones incrementales como deducción de tipos con `auto`, `typeof`, una forma de palabra clave de `static_assert`, una sintaxis de inicialización más limpia y la eliminación de construcciones heredadas como los trigraphs y las definiciones de funciones al estilo K&R. Los comentaristas están divididos sobre si estos cambios mejoran realmente C: algunos celebran mejores macros genéricas, aritmética comprobada más segura y una mayor alineación con extensiones existentes de compiladores y con C++, mientras que otros los ven como retoques superficiales que no abordan problemas de larga data como las cadenas, los módulos y una gestión de recursos más segura. La conversación también sitúa a C23 en un panorama más amplio en el que muchos proyectos nuevos de sistemas prefieren C++ o Rust, y donde lenguajes alternativos (Zig, D, Nim, Ada, etc.) compiten por ofrecer una interoperabilidad con C más segura o más ergonómica.
Auto, typeof y “genéricos” en C23
- Reutilizar
autoes visto por algunos como una elección extraña; muchos esperan que sea una norma de estilo “prohibida” en código C serio, a diferencia de C++. - Otros sostienen que en C sí es realmente útil:
- Evita nombres de tipo verbosos y los prefijos
struct/enum. - Ayuda con macros genéricas (p. ej.,
SWAP(a,b)usandoauto tmp = a;) y con tipos enteros de ancho fijo. - Estandariza las extensiones existentes
__auto_type.
- Evita nombres de tipo verbosos y los prefijos
- También se añade
typeof; algunos señalan que ahora se puede escribirconst typeof(var1) tmp = var1;. - Debate sobre si
_Genericrealmente cuenta como “genéricos”: algunos lo ven como sobrecarga/un switch sobre el tipo, no como estructuras de datos paramétricas; otros dicen que aun así alcanza el umbral de “genérico”.
Otros ajustes de lenguaje en C23
static_assertpasa a ser una palabra clave; C11 ya tenía_Static_asserty una macro, pero ahora se puede usar sin<assert.h>.func()ahora es explícitamente equivalente afunc(void), y se permiten parámetros sin nombre.- La inicialización de
structcon{}(zero-init) ahora es válida (struct foo x = {};), alineándose con C++. - La eliminación de los trigraphs y de las antiguas declaraciones de funciones al estilo K&R es bienvenida como limpieza de rarezas históricas.
- Algunos desean que C23 hubiera incluido una función integrada tipo
defer/RAII; existe una propuesta así, pero sigue siendo “exploratoria”.
Soporte de toolchain y compiladores
- La referencia a cppreference muestra que GCC 13 tiene un soporte de C23 comparativamente amplio; Clang va rezagado en varias características.
- Las explicaciones ofrecidas: el diseño modular de LLVM y los forks corporativos ralentizan la evolución del frontend; grandes contribuidores se centran en backends o en otros lenguajes.
- Se informa que Pelles C soporta casi todas las características de C23, incluido
#embed. - MSVC históricamente descuidó C, pero más recientemente soporta C17 (salvo algunas características opcionales de C99); el momento en que llegue C23 no está claro.
C vs C++ y filosofía del lenguaje
- Algunos argumentan que C++ ya es “un mejor C” y que C23 es sobre todo una retroportación de características de C++.
- Otros responden que C y C++ ahora sirven a dominios distintos; la complejidad de C++, la metaprogramación y la generación de código oculta se ven como inadecuadas para algunos casos de uso embebidos o de bajo nivel.
- Las analogías varían: desde “C++ es un cybertruck frente a la bicicleta de C” (criticada como inexacta) hasta “C son herramientas manuales, C++ añade herramientas eléctricas”.
- Debate sobre excepciones y RAII en sistemas embebidos: algunos dicen que RAII es sencillo y útil; otros se preocupan por ciclos de vida de objetos menos explícitos.
Cabeceras, módulos y superficie de API
- Algunos desearían que C tuviera módulos/imports reales en lugar de cabeceras, para evitar duplicación y acelerar compilaciones, posiblemente con
importjunto al legado#include. - A otros les gusta la separación de cabecera/implementación de C para exponer claramente una API pública; señalan que esto es ortogonal a si el lenguaje tiene o no un sistema de módulos.
- Se comenta que unos módulos más fuertes podrían romper parte de la interoperabilidad C/C++, lo cual es políticamente sensible.
Alternativas con seguridad de memoria y FFI con C
- Un largo subhilo explora “lenguajes pequeños, estables y seguros en memoria con excelente FFI con C y sin una gran pérdida de rendimiento”.
- Entre los candidatos mencionados están Zig, D, Rust, Nim, V, Vala, LuaJIT, Ada, varios Schemes y Lisps, Swift, Julia y Go.
- Compromisos destacados:
- La verdadera seguridad de memoria suele implicar GC o borrowing al estilo Rust; ambos complican el FFI y/o la simplicidad.
- Un FFI con C fácil y de sobrecoste cero tiende a debilitar las garantías de seguridad fuertes (los errores pueden colarse desde C).
- Varios comentaristas sostienen que la lista de deseos exacta puede ser imposible de satisfacer por completo; como mucho se puede aproximar con distintos compromisos.