# C23 (Estándar de C)

C23, formalmente ISO/IEC 9899:2024, es el estándar abierto actual para el lenguaje de programación C, que reemplaza a C17 (ISO/IEC 9899:2018). Su desarrollo comenzó en 2016, bajo el nombre de C2x, y se publicó el 31 de octubre de 2024. El borrador libre más similar al publicado es el documento N3220 (ver Textos disponibles, más abajo). La primera reunión del GT14 para el borrador de C2x se celebró en octubre de 2019, se celebraron reuniones remotas virtuales en 2020 debido a la pandemia de COVID-19, y luego varias reuniones por teleconferencia hasta 2024.
En C23, el valor de __STDC_VERSION__ cambia de 201710L a 202311L. Los nombres comunes "C17" y "C23" reflejan estos valores, que fueron fijados antes de la adopción final, en lugar de los años en los identificadores de las normas ISO (9899:2018 y 9899:2024).
| Predecesor: C17 (Estándar de C) | Estándares de C | Sucesor: - |

## Características

A continuación se enumeran los cambios integrados en el último borrador del estándar C23.

### Biblioteca estándar
#### Nuevas funciones

* memset_explicit en <string.h> para borrar información sensible, donde la operación de memoria siempre debe ser realizada, sin importar las optimizaciones.
* memccpy en <string.h> para concatenar cadenas de forma eficiente – similar a las extensiones POSIX y SVID.
* strdup y strndup en <string.h> para crear una copia de una cadena – similar a las extensiones POSIX y SVID.
* memalignment en <stdlib.h> para determinar el alineamiento de bytes de un puntero.
* Añade functiones / macros / tipos para trabajar con bits en un nuevo fichero de cabecera <stdbit.h>. Todos empiezan con stdc_ para minimizar conflictos con código existente y librerías de terceros.
** En las siguientes, sustituye * con uc, us, ui, ul, ull para obtener el nombre de 5 funciones diferentes, o déjalo vacío para una maro genérica.
** stdc_count_ones* y stdc_count_zeros* para contar el número de 1 o 0 en los bits de un valor.
** stdc_leading_ones* y stdc_leading_zeros* para contar el número de 1 o 0 al principio de los bits de un valor.
** stdc_trailing_ones* y stdc_trailing_zeros* para contar el número de 1 o 0 al final de los bits de un valor.
** stdc_first_leading_one* y stdc_first_leading_zero* para buscar el primer bit con un 1 o 0 en los bits de un valor.
** stdc_first_trailing_one* y stdc_first_trailing_zero* para buscar el último bit con un 1 o 0 en los bits de un valor.
** stdc_has_single_bit* para determinar si un valor tiene un solo bit a 0 (es decir, si es una potencia de 2).
** stdc_bit_floor* para encontrar el primer entero potencia de dos que es menor o igual a ese valor.
** stdc_bit_ceil* para encontrar el primer entero potencia de dos que es mayor o igual a ese valor.
** stdc_bit_width* para determinar el número de bits necesarios para almacenar un valor.
* timegm en <time.h> una estructura time en un valor callendar - similar a las funciones en las librerías glibc y musl.
* Nuevas funciones en <math.h> basadas en las recomendaciones del estándar IEEE 754-2019 como, por ejemplo, funciones trigonométricas que operan en unidades de $\pi x$ y exp10.

#### Funciones ya existentes

* Añade el especificador de conversión binaria %b a la familia de funciones printf .
* Añade el especificador de conversión binaria %b a la familia de funciones scanf .
* Añade soporte de conversión binaria 0b y 0B a las familias de funciones strtol y wcstol .
* Hace que las funciones bsearch, bsearch_s, memchr, strchr, strpbrk, strrchr, strstr y sus contrapartes "wide" (wchar_t) wmemchr, wcschr, wcspbrk, wcsrchr, wcsstr, devuelvan un objeto calificado como const si se les pasó uno.

### Preprocesador

* Añade directivas #elifdef y #elifndef, que son esencialmente equivalentes a #elif defined y #elif !defined . Ambas directivas se agregaron al estándar C++23 y GCC 12.
* Añade la directiva #embed para la inclusión de recursos binarios y __has_embed permitiendo que la disponibilidad de un recurso sea verificada por directivas del preprocesador.
* Añade la directiva #warning.
* Añade la macro __has_include permitiendo que las directivas del preprocesador verifiquen la disponibilidad de un encabezado.
* Añade la macro __has_c_attribute permitiendo que la disponibilidad de un atributo sea verificada por el preprocesador. (consulte el grupo "Compatibilidad con C++ " para conocer la nueva función de atributo)
* Añade la macro funcional __VA_OPT__ para las macros variádicas, que se expande a su argumento solo si se ha pasado un argumento variádico a la macro que lo contiene.

### Tipos

* Añade nullptr_t, un tipo de puntero nulo .
* Añade _BitInt (N) y unsigned _BitInt (N) tipos para números enteros con precisión de bits. Añade BITINT_MAXWIDTH macro para ancho de bit máximo.
* Añade las macros ckd_add, ckd_sub y ckd_mul para operaciones comprobadas con números enteros.
* Los tipos modificados de forma variable (pero no los VLA, que son variables automáticas asignadas en la pila) se convierten en una característica obligatoria.
* Mejor soporte para el uso de const con matrices.
* Estandarización del operador typeof (...) .
* El significado la palabra clave auto se modificó para proveer al lenguaje de inferencia de tipo. Pero se sigue conservando su antiguo significado de especificador de clase de almacenamiento si se usa junto con un tipo. A diferencia de C++, C23 permite la inferencia de tipos solo para definiciones de objetos (no se puede inferir el tipo de retorno de una función o el tipo de parámetro de una función).
* Se cambiaron las reglas de compatibilidad para estructuras, uniones y tipos enumerados para permitir una redeclaración de un tipo compatible con la misma etiqueta.
* Los números enteros de ancho exacto ahora pueden superar intmax_t (N2888).

### Constantes

Las siguientes constantes son definidas por el estándar:
* nullptr para el tipo nullptr_t .
* Sufijos literales enteros wb y uwb para los tipos _BitInt(N) y unsigned _BitInt(N). De esta forma, 6u wb produce un unsigned _BitInt(3) y -6 wb produce un signed _BitInt(4) que tiene tres bits de valor y un bit de signo.
* Prefijos para constantes literales binarios 0b y 0B,. Por ejemplo: 0b10101010 (equivale a 0xAA).
* El caracter ' como un separador de dígitos para las constantes literales. Por ejemplo: 0xFE'DC'BA'98 (equivalente a 0xFEDCBA98), 299'792'458 (equivalente a 299792458 ) y 1.414'213'562 (equivalente a 1,414213562 ).
* La capacidad de especificar el tipo subyacente de un enumerado .
* Permite enumerados sin un tipo subyacente fijo para almacenar valores que no se pueden representar mediante int .

### Palabras clave

Las siguientes palabras claves son definidas:
* true y false
* alignas, alignof, bool, static_assert, thread_local. Las palabras clave definidas previamente se convierten en alternativas equivalentes: _Alignas, _Alignof, _Bool, _Static_assert, _Thread_local .
* _BitInt (ver grupo "tipos")
* typeof y typeof_unqual (ver grupo "tipos")
* nullptr (ver grupo "constantes")
* constexpr (ver grupo "otros")
* _Decimal32, _Decimal64, _Decimal128 para aritmética de punto flotante decimal (opcional) (ver grupo "otros")

### Sintaxis

* Las etiquetas pueden aparecer antes de las declaraciones y al final de las declaraciones compuestas .
* Parámetros sin nombre en definiciones de funciones.
* Inicialización a cero con (incluida la inicialización de VLA).
* Las funciones variádicas ya no necesitan un argumento con nombre antes de los puntos suspensivos y la macro va_start ya no necesita un segundo argumento ni evalúa ningún argumento después del primero si está presente.
* Añade la sintaxis de atributos al estilo de C++11, usando corchetes dobles [] . Además de los atributos de C++11 que se enumeran a continuación, añade nuevos atributos:
** [[unsequenced]] permite optimizaciones del compilador para funciones que producen salidas repetibles solo en función de sus parámetros
** [[reproducible]], similar a [[unsequenced]], pero para funciones cuyo orden de llamada también importa
* Añade _Static_assert con un solo argumento para mejorar la compatibilidad con C++17 .
* Funciones sin argumentos enumerados en su prototipo (por ejemplo, void foo ) se entienden como si no tomaran argumentos (consulte la eliminación de las declaraciones de funciones al estilo de K&R)

### Compatibilidad con C++

* Varios cambios en la sintaxis mejoran la compatibilidad con C++, como etiquetas antes de las declaraciones, argumentos de funciones sin nombre, inicialización a cero con, funciones variádicas sin argumentos nombrados, atributos al estilo de C++11, _Static_assert (ver Sintaxis). Para las etiquetas al final de declaraciones compuestas se realizó un cambio correspondiente en C++23 .
* Añade atributos al estilo de C++ (ver Sintaxis). Añade los atributos [[ deprecated ]], [[ fallthrough ]], [[ maybe_unused ]], [[ nodiscard ]], y [[ noreturn]] para mejorar la compatibilidad con C++11.
* Marca com obsoletos: _Noreturn, noreturn y el encabezado <stdnoreturn.h> (características introducidas en C11) .
* Se permiten atributos duplicados por compatibilidad con C++23 . Todos los atributos estándar también pueden estar rodeados por guiones bajos dobles. Por ejemplo [[ __deprecated__ ]] es equivalente a [[ deprecated ]].
* Añade el prefijo u8 a los literales de caracteres para representar la codificación UTF-8 por compatibilidad con C++17 .
* Añade las directivas #elifdef y #elifndef, por compatibilidad con C++23 (ver grupo "preprocesador")

### Otras características

* Añade soporte para la norma ISO/IEC 60559:2020, la versión actual del estándar IEEE 754 para aritmética de punto flotante, con aritmética de punto flotante binaria extendida y aritmética de punto flotante decimal (opcional).
* El especificador constexpr para objetos pero no para funciones, a diferencia del equivalente de C++ .
* Añade el tipo char8_t, para almacenar datos codificados en UTF-8 y cambia el tipo de constantes de caracteres u8 y literales de cadena a char8_t . Además, las funciones mbrtoc8 y c8rtomb convierten un carácter multibyte estrecho a codificación UTF-8 y un único punto de código de UTF-8 a una representación de carácter multibyte respectivamente.
* Aclarar que todos las cadenas y los literales char16_t se codificarán en UTF-16 y todas las cadenas y los literales char32_t se codificarán en UTF-32, a menos que se especifique explícitamente lo contrario.
* Permitir que los especificadores de clase de almacenamiento aparezcan en las definiciónes literales compuestas (compound literals).

## Características obsoletas

Algunas características antiguas se han eliminado del borrador de trabajo de C23:
   * Eliminar trígrafos .
   * Eliminar las definiciones/declaraciones de funciones al estilo de K&R (sin información sobre los argumentos de la función).
   * Eliminar representaciones de números enteros con signo distintos del complemento a dos. Se requerirá una representación entera con signo de complemento a dos .
   * Las macros * _HAS_SUBNORM en <float.h>.

## Compatibilidad de compiladores

Los siguientes compiladores implementan un indicador de compilador experimental para este estándar:
* GCC 9,
* Clang 9.0,
* Pelles C 11.00

## Textos disponibles

Al igual que otras ediciones del estándar C, el texto oficial ISO del estándar no está disponible gratuitamente.
El último borrador de trabajo previo al C23 que se hizo público fue el N3096, de fecha 01-04-2023. En los meses posteriores a este borrador, se realizaron cientos de cambios antes de producir el borrador de trabajo N3149 con fecha del 9 de julio de 2023 y el borrador oficial de la norma N3219 con fecha del 22 de febrero de 2024. Ninguno de estos borradores posteriores es público.
En la misma fecha en que se anunció el proyecto de norma N3219, se hizo público un nuevo borrador de trabajo N3220. Si bien este documento se describe oficialmente como un borrador de la futura versión "C2Y" de la norma, el "Informe del editor" adjunto especifica que la N3220 difiere del borrador de la norma C23 N3219 solo por una corrección a una nota al pie en el Anexo K.