Edición C23 de Modern C
(gustedt.wordpress.com)- La edición revisada de Modern C adaptada al nuevo estándar de C está disponible para descarga gratuita, lo que permite volver a consultar y estudiar el lenguaje C con base en C23
- El eje de la revisión es la incorporación de C23, con foco en facilitar la transición al nuevo estándar en sincronía con el proceso y los tiempos de publicación de ISO
- Las nuevas versiones de los principales compiladores ya implementan la mayoría de las funciones de C23, por lo que los cambios del libro van más allá de una presentación experimental y se conectan con entornos de uso reales
- Cambios del lenguaje y la biblioteca como
_BitInt(N),nullptr,auto,typeofyconstexprse reflejan ampliamente, e impactan también en la forma de escribir código C existente - Se agregaron apéndices de transición y encabezados include temporales para poder probarlo de inmediato en plataformas existentes, aunque el MEAP de Manning todavía sigue en curso
Materiales gratuitos y documentos del estándar
- La edición C23 de Modern C se puede descargar gratis
- Descarga: https://hal.inria.fr/hal-02383654
- En la página dedicada del libro también se pueden encontrar materiales relacionados
- Página dedicada: https://gustedt.gitlabpages.inria.fr/modern-c/
- En esa página también está el enlace para descargar los ejemplos de código incluidos con el libro
- La edición revisada ajusta varias explicaciones, pero su objetivo central es reflejar C23, el nuevo estándar de C
- Entre los documentos de acceso público, el material más cercano al contenido del nuevo estándar es el PDF N3220
- Las nuevas versiones de los principales compiladores ya implementan la mayor parte de las nuevas funciones que trae C23
Cambios del lenguaje en C23 y apoyo para la transición
- Los cambios relacionados con enteros ocupan una parte importante
- Se agrega el nuevo tipo de precisión de bits
_BitInt(N) - Se agregan nuevos encabezados de la biblioteca C para aritmética con verificación de overflow y manipulación de bits
- Se refleja la posibilidad de tipos de 128 bits en arquitecturas modernas
- También incluye mejoras sustanciales en los tipos enum
- Se agrega el nuevo tipo de precisión de bits
- También se incluyen otros conceptos nuevos de C23
- La constante
nullptry su tipo base - Anotaciones sintácticas mediante attributes
- Herramientas de programación genérica de tipos, incluidas
autoytypeof - Inicialización predeterminada con
{}, aplicable también a arreglos de longitud variable constexprpara constantes con nombre de todos los tipos
- La constante
- El nuevo material también cubre expresiones compuestas, lambdas, “internacionalización” y un enfoque integral sobre fallas de programa
- Se agregaron apéndices y encabezados include temporales para poder empezar con C23 de inmediato en plataformas existentes
- El MEAP de la nueva edición de Manning todavía está abierto
- MEAP: https://www.manning.com/books/modern-c-third-edition
- Aún no se conoce la fecha de publicación final de la edición C23 en la versión de Manning
1 comentarios
Opiniones de Hacker News
A diferencia de little-endian, que es el orden de almacenamiento de mi máquina, al esquema en el que la representación de los dígitos más significativos viene primero se le llama big-endian; pero decir que ambos se usan comúnmente en procesadores modernos me suena algo exagerado, porque casi no queda nada aparte de s390x
Supongo que pronto llegará el comentario sobre la arquitectura big-endian de nicho/obsoleta favorita de todos
Como en otro comentario destacado, que algo sea moderno no necesariamente significa que sea popular o ampliamente usado
AIX e IBM i quizá no estén tan activos como los mainframes de IBM, pero se puede decir que AIX está más vivo incluso que Solaris o HP/UX, y más aún si se lo compara con los muchos Unix comerciales de antes. IBM i también apenas se mantiene, pero está mucho más vivo que plataformas midrange legadas de la competencia cuyo soporte del proveedor terminó oficialmente, como HP MPE
El aspecto más importante de C es la portabilidad. La clave es que va desde microcontroladores pequeños hasta casi cualquier plataforma de cómputo, y me pregunto si una nueva versión de C llegará a adoptarse en esa medida
Si quisiera usar lo más avanzado, creo que elegiría C++2x o Rust antes que C. ¿Me estoy perdiendo de algo? Me intriga qué beneficios ofrece este supuesto C moderno
Si hablamos de lo más avanzado, recomendaría Zig. Tiene una complejidad de lenguaje mucho menor que C++ moderno y Rust. Un buen efecto secundario, menos llamativo, de C23 es que alinea mejor sintaxis como
... = {}y{0}con C++, lo que hace menos molesto para los mantenedores de bibliotecas en C dar soporte a quienes quieren compilar código C con un compilador de C++0bse usa ampliamente en el mundo de los microcontroladoresLas cadenas de herramientas para microcontroladores suelen estar construidas sobre GCC, así que obtienen las funciones gratis. Todavía hay compiladores C propietarios que siempre van atrasados, pero ya no son tan importantes como hace 20 años
Si no apuntas a embedded o a un conjunto muy amplio de arquitecturas, no hay razón para no usar C23 desde hoy
thread_localya se usa en algunas plataformas de microcontroladores, pero antes de C11 era completamente ilegal. Aun así, simplifica mucho la gestión de memoria en entornos con hilos¿Hay alguna razón para tener que entrar al mundo de C++ solo por eso?
Personalmente, cosas como
guard,defer,auto,constexprynullptrhacen que C sea mucho más complejo. Uno elige C porque necesita simplicidad; si quisiera complejidad, normalmente elegiría C++ aunque no me gustara, o mejor Go, o Elixir si fuera para servidores_BitInt(N)también es feo, y me recuerda a_Bool, que por suerte ahora esbool.constexprynullptrhuelen demasiado a C++. Aun así, Modern C es un libro excelente, y me ha servido mucho para C99, que es lo que pienso seguir usandoNULLse responde leyendo los documentos relacionados, gracias a una de las pocas ventajas de la estandarización ISO: https://wg21.link/p2312En resumen, pasar un argumento
NULLa una macro type-generic puede producir resultados sorprendentes, y el estatus de expresiones condicionales como(1 ? 0 : NULL)y(1 ? 1 : NULL)depende de cómo esté definidoNULL. Además, pasarNULLa una función variádica que espera un puntero puede tener consecuencias graves. En muchas arquitecturas actuales,intyvoid*tienen tamaños distintos, así que siNULLes simplemente0, se pasa a la función un argumento del tamaño incorrectoEs parecido a construir una casa. Un martillo y un destornillador son muy simples, y una grúa es extremadamente compleja, pero lo que simplifica construir una casa es la grúa. Si quisieras construir una casa solo con un martillo y un destornillador, tendrías que diseñar un procedimiento enormemente complejo
Con los lenguajes de programación pasa lo mismo. Crear contenedores genéricos en C++ es trivial, pero en C es muy difícil. Se puede imitar hasta cierto punto con
void *y casts manuales, pero es engorroso, propenso a errores y vuelve el código más complejoLo mismo ocurre con
std::sortyqsort. Gracias al poder de las plantillas y los objetos función, la implementación es más simple y rápida. No hace falta pasarvoid *ni desreferenciar en tiempo de ejecución, y la comparación puede ponerse en la propia definición de la función. No hay llamada indirecta ni paso por pila, e incluso se puede inlinear la función de comparación. La complejidad del lenguaje no significa complejidad de implementaciónautoes útil sobre todo al trabajar con macros type-generic, pero conviene no usarlo en código común. Ojalá evitemos locuras como almost always auto, que estuvo de moda un tiempo en el mundo C++Lamentablemente hay pequeñas diferencias entre compiladores. Si no recuerdo mal, Clang implementa
autoal estilo C++ y GCC implementaautoal estilo C, así que había diferencias sutiles con punterosauto. No sé si esa diferencia ya se corrigió_BitInt(N)normalmente no se usa directamente, sino mediante untypedefcon el ancho necesario. Por ejemplo,typedef _BitInt(2) u2;. Sintaxis feas como_Bson necesarias porque las combinaciones de guion bajo seguido de mayúscula están reservadas en el estándar C, para evitar conflictos con código existente al agregar pequeñas funciones al lenguaje. El nombre_Boolse debe a la misma razón. Hasta donde sé,deferen realidad no entró en C23La definición anterior ni siquiera especificaba si
NULLera un puntero o un entero. Por eso, en plataformas que no seguían el requisito de Posix de((void*)0), era una trampa bajo los pies: no era ni de tipo puntero ni del tamaño de un punteroQue
constexprynullptrhuelan a C++ probablemente se debe a que fueron reimportados desde C++. Aun así, se puede seguir usandoNULL; por fuera, parece que fue redefinido comonullptrexeclp("echo", "echo", "Hello, world!", NULL);Este código no tiene ese bug:
execlp("echo", "echo", "Hello, world!", nullptr);Esto también está bien:
execlp("echo", "echo", "Hello, world!", (char *)NULL);Iba a preguntar si había una buena lista de libros de C, pero terminé encontrando la respuesta por mi cuenta. Aquí clasifican Modern C como de nivel intermedio
https://stackoverflow.com/questions/562303/the-definitive-c-...
Como acompañantes modernos de C para K&R, creo que 21st Century C de Ben Klemens y C Programming: A Modern Approach de King son alternativas más accesibles
En lo personal, prefiero Effective C antes que Modern C. Modern C es muy riguroso, al punto de sentirse como leer una especificación anotada del lenguaje, algo que puede ser necesario para expertos, pero que para alguien como yo, que usa C de forma ligera, resulta tedioso de leer
Algunas de las extensiones High C de Metaware me gustan bastante
https://news.ycombinator.com/item?id=41647843
https://news.ycombinator.com/item?id=38938402
Desde hace más de un año uso C++ moderno en un proyecto personal, un intérprete de lenguaje, pero por la carga mental de C++ y los problemas de herramientas sigo pensando en cambiarlo a C. IntelliSense de Visual Studio todavía casi no funciona cuando se usan módulos de C++20, y por fallas del lenguaje demasiadas cosas terminan empujadas a la interfaz, haciendo que los tiempos de compilación se vuelvan horribles
Por otro lado, ya me acostumbré demasiado a las clases, los métodos, la programación genérica y los espacios de nombres, así que quizá ya caí en la trampa
Para ese caso, ¿has considerado C#? Visual Studio encaja mucho mejor con C#
En Preview de macOS, al hacer clic en los enlaces del índice de la barra lateral, no funcionan correctamente
Hace apenas unos años que pude confiar en que todos los compiladores de C soportaran C99 en una biblioteca que mantengo: https://github.com/eyalroz/printf
Pero, como era de esperarse, unos años después se abrió un issue pidiendo compatibilidad con C89 por culpa de alguna toolchain embebida antiquísima. Así que C23 está bueno, pero se siente como algo de lo que volveremos a hablar dentro de unos 20 años
¿Alguien puede enlazar algún texto que explique, de forma práctica, por qué C está básicamente estancado en C99? Casi no veo proyectos dignos de mencionar que aprovechen funciones posteriores a C11
Como C estuvo prácticamente congelado durante décadas, parece que su base de usuarios se autoseleccionó entre gente a la que le gusta C tal como es y no le molesta soportar compiladores viejos y llenos de rarezas. Quienes perdieron la paciencia o querían un lenguaje del siglo XXI se fueron a C++/Rust/Zig, etc.
Alrededor de 2010, MSVC todavía era muy importante, lo cual suena raro desde una perspectiva actual, en la que parece que la mayoría de los desarrolladores se mudaron a Linux. Por otro lado, tampoco hay muchos proyectos que realmente necesiten funciones de C11. C11 también quitó las VLA de C99, aunque no fue una pérdida muy lamentable. C23 podría ser la primera versión desde C99 a la que muchas bases de código en C realmente valga la pena actualizar