
C99 ( C9X durante su desarrollo, formalmente ISO/IEC 9899:1999 ) es una versión anterior del estándar abierto del lenguaje de programación C. [ 1 ] Amplía la versión anterior ( C90 ) con nuevas características para el lenguaje y la biblioteca estándar , y ayuda a las implementaciones a aprovechar mejor el hardware informático disponible, como la aritmética de punto flotante IEEE 754-1985 y la tecnología de compiladores. [ 2 ] La versión C11 del estándar del lenguaje de programación C, publicada en 2011, actualiza C99.
Historia
Tras la publicación del estándar oficial del lenguaje de programación C por parte de ANSI en 1989, que se convirtió en estándar internacional en 1990, la especificación del lenguaje C se mantuvo relativamente estática durante un tiempo, mientras que C++ continuó evolucionando, principalmente durante su propio proceso de estandarización. La Enmienda Normativa 1 creó un nuevo estándar para C en 1995, pero solo para corregir algunos detalles del estándar de 1989 y añadir un soporte más amplio para conjuntos de caracteres internacionales. El estándar se revisó nuevamente a finales de la década de 1990, lo que llevó a la publicación de ISO/IEC 9899:1999 en 1999, que fue adoptado como estándar ANSI en mayo de 2000. El lenguaje definido por esa versión del estándar se conoce comúnmente como "C99". El estándar internacional C es mantenido por el grupo de trabajo ISO/IEC JTC1/SC22 /WG14.
Diseño

C99 es, en su mayor parte, compatible con versiones anteriores de C89, pero es más estricto en algunos aspectos. [ 3 ]
En particular, una declaración que carece de un especificador de tipo ya no se intasume implícitamente. El comité de estándares de C decidió que era más valioso que los compiladores diagnosticaran la omisión involuntaria del especificador de tipo que procesar silenciosamente el código heredado que dependía de la asunción implícita int. En la práctica, es probable que los compiladores muestren una advertencia, asuman el tipo inty continúen traduciendo el programa.
C99 introdujo varias características nuevas, muchas de las cuales ya se habían implementado como extensiones en varios compiladores: [ 4 ]
- funciones en línea
- Declaraciones y código intercalados: la declaración de variables ya no se limita al ámbito del archivo ni al inicio de una instrucción compuesta (bloque).
- varios tipos de datos nuevos , incluidos
long long inttipos enteros extendidos opcionales, un tipo de datos booleano explícito (_Bool), y tipos complejos (_Complexespecificador de tipo) para representar números complejos - matrices de longitud variable (aunque posteriormente relegadas en C11 a una característica condicional que las implementaciones no están obligadas a admitir)
- miembros de matriz flexibles
- soporte para comentarios de una sola línea que comienzan con
//(como el de BCPL , C++ y Java ) - nuevas funciones de biblioteca, como
snprintf - nuevos encabezados , como , , , y
<stdbool.h><complex.h><tgmath.h><inttypes.h> - funciones matemáticas (macro) genéricas de tipo, en
<tgmath.h>, que seleccionan una función de la biblioteca matemática en función de , , o argumentos, etc.floatdoublelong double - Soporte opcional para punto flotante IEEE 754-1985
- inicializadores designados. Por ejemplo, inicializar una estructura por nombres de campo: [ 5 ]
structXp={.i=1,.j=2}; - literales compuestos. Por ejemplo, es posible construir estructuras en llamadas a funciones: [ 6 ]
foo((structX){1,2}) - Compatibilidad con macros variádicas (macros con un número variable de argumentos)
restrictLa calificación permite una optimización de código más agresiva, eliminando las ventajas de acceso a matrices en tiempo de compilación que FORTRAN tenía anteriormente sobre ANSI C [ 7 ].- nombres de caracteres universales, que permiten que las variables de usuario contengan caracteres distintos del conjunto de caracteres estándar:
\u0040secuencias hexadecimales de cuatro u ocho dígitos.\U0001f431 - palabra clave
staticen índices de matriz en declaraciones de parámetros [ 8 ] : Por ejemplo, le indica al compilador que cada vez que se llama, el puntero pasado definitivamente no es nulo y apunta a una matriz de al menos 100 s. [ 9 ] [ 10 ]voidfoo(intbar[static100]);foo()barint
Algunas características de C99 fueron excluidas de C++ , en particular los arreglos de longitud variable. C++ ofrece estructuras de datos secuenciales para std::vector<T>propósitos similares.
Compatibilidad con coma flotante IEEE 754
Una característica principal de C99 es su soporte numérico, y en particular su soporte para el acceso a las características del hardware de punto flotante IEEE 754-1985 (también conocido como IEC 60559) presente en la gran mayoría de los procesadores modernos (definido en el "Anexo F: Aritmética de punto flotante IEC 60559"). Las plataformas que no disponen de hardware IEEE 754 también pueden implementarlo por software. [ 2 ]
En plataformas con coma flotante IEEE 754:
floatse define como precisión simple IEEE 754 , se define como precisión doble y se define como precisión extendida IEEE 754 (por ejemplo, precisión extendida doble de 80 bits de Intel en plataformas x86 o x86-64 ), o alguna forma de precisión cuádruple cuando esté disponible; de lo contrario, es precisión doble.doublelong double- Las cuatro operaciones aritméticas y la raíz cuadrada se redondean correctamente según lo define la norma IEEE 754.
- La evaluación de expresiones se define para realizarse mediante uno de tres métodos bien definidos, que indican si las variables de punto flotante se convierten primero a un formato más preciso en las expresiones:
FLT_EVAL_METHOD == 2indica que todos los cálculos intermedios internos se realizan por defecto con alta precisión (long double) cuando esté disponible (por ejemplo, double extended de 80 bits ),FLT_EVAL_METHOD == 1realiza todas las expresiones intermedias internas con doble precisión (a menos que un operando sea long double), mientras queFLT_EVAL_METHOD == 0especifica que cada operación se evalúa solo con la precisión del operando más amplio de cada operador. El tipo de resultado intermedio para operandos de una precisión dada se resume en la tabla adyacente.
FLT_EVAL_METHOD == 2tiende a limitar el riesgo de errores de redondeo que afectan a expresiones numéricamente inestables (véase la justificación del diseño de IEEE 754 ) y es el método predeterminado diseñado para el hardware x87 , pero produce un comportamiento poco intuitivo para el usuario desprevenido; [ 11 ]FLT_EVAL_METHOD == 1 fue el método de evaluación predeterminado utilizado originalmente en K&R C , que promovió todos los floats a double en las expresiones; y FLT_EVAL_METHOD == 0también se usa comúnmente y especifica una "evaluación al tipo" estricta de los operandos. (Para gcc , es el predeterminado en x86 de 32 bits, y es el predeterminado en x86-64 de 64 bits, pero se puede especificar en x86-64 con la opción -mfpmath=387). Antes de C99, los compiladores podían redondear los resultados intermedios de forma inconsistente, especialmente cuando se utilizaba hardware de punto flotante x87 , lo que daba lugar a un comportamiento específico del compilador; [ 12 ] tales inconsistencias no están permitidas en los compiladores que cumplen con C99 (anexo F).FLT_EVAL_METHOD == 2 FLT_EVAL_METHOD == 0 FLT_EVAL_METHOD == 2
Ejemplo
El siguiente ejemplo de código C99 comentado para calcular una función de fracción continua demuestra las características principales:
#incluir <assert.h>#incluir <fenv.h>#include <float.h>#include <math.h>#include <stdio.h>#include <stdbool.h>#include <tgmath.h>double compute_fn ( double z ) { // [1]#pragma STDC FENV_ACCESS ON // [2]assert ( FLT_EVAL_METHOD == 2 ); // [3]si ( isnan ( z )) { // [4]puts ( "z no es un número" );}si ( isinf ( z )) {puts ( "z es infinito" );}long double r = 7.0 - 3.0 / ( z - 2.0 - 1.0 / ( z - 7.0 + 10.0 / ( z - 2.0 - 2.0 / ( z - 3.0 )))); // [5, 6]feclearexcept ( FE_DIVBYZERO ); // [7]bool raised = fetestexcept ( FE_OVERFLOW ); // [8]si ( se elevó ) {puts ( "Desbordamiento inesperado." );}devolver r ;}int main ( void ) {#ifndef __STDC_IEC_559__puts ( "Advertencia: __STDC_IEC_559__ no está definido. El punto flotante IEEE 754 no es totalmente compatible." ); // [9]#finsi#pragma STDC FENV_ACCESS ON#ifdef PRUEBA_ESTABILIDAD_NUMÉRICA_UPfesetround ( FE_UPWARD ); // [10]#elif TEST_NUMERIC_STABILITY_DOWNfesetround ( FE_DOWNWARD );#finsiprintf ( "%.7g \n " , compute_fn ( 3.0 ));printf ( "%.7g \n " , cálculo_fn ( NAN ));devolver 0 ;}Notas a pie de página:
- Compilar con:
gcc-std=c99-mfpmath=387-otest_c99_fptest_c99_fp.c-lm - Dado que en esta función se manipulan los indicadores de estado IEEE 754, se necesita esta directiva #pragma para evitar que el compilador reorganice incorrectamente dichas pruebas durante la optimización. (Las directivas pragma suelen depender de la implementación, pero las que tienen el prefijo #pragma
STDCestán definidas en el estándar C). - C99 define un número limitado de métodos de evaluación de expresiones: se puede comprobar el modo de compilación actual para asegurar que cumple con los supuestos bajo los que se escribió el código.
- Se pueden probar y configurar valores especiales como NaN e infinito positivo o negativo.
long doublese define como precisión doble extendida IEEE 754 o precisión cuádruple si está disponible. Usar una precisión mayor que la requerida para los cálculos intermedios puede minimizar el error de redondeo [ 13 ] (el typedefdouble_tse puede usar para código que es portable en todosFLT_EVAL_METHODlos s).- La función principal a evaluar. Aunque parezca que algunos argumentos para esta fracción continua, por ejemplo, 3.0, provocarían un error de división por cero, en realidad la función está bien definida en 3.0 y la división por cero simplemente devolverá un +infinito que, por lo tanto, dará como resultado un valor finito: IEEE 754 está diseñado para no detectar tales excepciones por defecto y está diseñado para que puedan ignorarse con frecuencia, como en este caso. (Si
FLT_EVAL_METHODse define como 2, todos los cálculos internos, incluidas las constantes, se realizarán con precisión de tipo long double; siFLT_EVAL_METHODse define como 0, se requiere un cuidado adicional para garantizar esto, incluyendo posiblemente conversiones de tipo adicionales y la especificación explícita de constantes como long double). - Como en este caso la señal de división por cero que se activa no es un error, simplemente se puede descartar para borrar la señal y que pueda ser utilizada por código posterior.
- En algunos casos, otras excepciones pueden considerarse un error, como por ejemplo el desbordamiento (aunque de hecho se puede demostrar que esto no puede ocurrir en este caso).
__STDC_IEC_559__Esta macro solo debe definirse si el compilador y la biblioteca C implementan completamente la "aritmética de punto flotante del Anexo F IEC 60559" (los usuarios deben tener en cuenta que esta macro a veces se define cuando no debería).- El modo de redondeo predeterminado es redondear al más cercano (con la regla de redondeo par en los casos intermedios) para IEEE 754, pero
TEST_NUMERIC_STABILITY_UPse puede usar para diagnosticar inestabilidad numérica configurando explícitamente el modo de redondeo hacia + y - infinito (definiendo etc. en este ejemplo, durante la depuración). [ 14 ] Este método se puede usar incluso sicompute_fn()forma parte de una biblioteca binaria compilada por separado. Sin embargo, dependiendo de la función, no siempre se pueden detectar las inestabilidades numéricas.
Detección de versiones
__STDC_VERSION__Se define una macro estándar con un valor 199901Lpara indicar que hay soporte para C99. Al igual que con la __STDC__macro para C90, __STDC_VERSION__se puede usar para escribir código que se compilará de manera diferente para los compiladores C90 y C99, como en este ejemplo que garantiza que inlineesté disponible en ambos casos (reemplazándolo con staticen C90 para evitar errores del enlazador).
#if __STDC_VERSION__ >= 199901L /* "inline" es una palabra clave */ #else # define inline static #endifImplementaciones
La mayoría de los compiladores de C ofrecen soporte para al menos algunas de las características introducidas en C99.
Históricamente, Microsoft ha tardado en implementar nuevas características de C en sus herramientas Visual C++ , centrándose principalmente en dar soporte a los desarrollos de los estándares de C++. [ 15 ] Sin embargo, con la introducción de Visual C++ 2013, Microsoft implementó un subconjunto limitado de C99, que se amplió en Visual C++ 2015. [ 16 ]
Trabajo futuro
Desde la ratificación del estándar C de 1999, el grupo de trabajo de estándares preparó informes técnicos que especifican una mejor compatibilidad con el procesamiento integrado, tipos de datos de caracteres adicionales ( compatibilidad con Unicode ) y funciones de biblioteca con comprobación de límites mejorada . Se sigue trabajando en informes técnicos que abordan la coma flotante decimal, funciones matemáticas especiales adicionales y funciones adicionales de asignación dinámica de memoria . Los comités de estándares de C y C++ han estado colaborando en las especificaciones para la programación multihilo .
La siguiente revisión del estándar C, C11 , fue ratificada en 2011. [ 44 ] El comité de estándares C adoptó directrices que limitaban la adopción de nuevas características que no hubieran sido probadas por implementaciones existentes. Se dedicó mucho esfuerzo al desarrollo de un modelo de memoria , con el fin de clarificar los puntos de secuencia y dar soporte a la programación multihilo .
Véase también
- Compatibilidad de C y C++
- Informe técnico de C++ 1
- IEEE 754 , para una discusión más detallada sobre el uso de IEEE 754
Referencias
- ↑ "ISO/IEC 9899:1999 - Lenguajes de programación - C" . Iso.org. 8 de diciembre de 2011. Consultado el 8 de abril de 2014 .
- 1 2 "Soporte de IEEE 754 en C99" (PDF) . IEEE . Archivado del original (PDF) el 28 de octubre de 2017. Recuperado el 15 de julio de 2021 .
- ↑ "Estándares - Uso de la colección de compiladores GNU (GCC)" . Gcc.gnu.org . Consultado el 8 de abril de 2014 .
- ↑ "Opciones de dialecto de C: uso de la colección de compiladores GNU (GCC)" . Gcc.gnu.org. 6 de mayo de 2009. Consultado el 8 de abril de 2014 .
- ↑ "Uso de la colección de compiladores GNU (GCC): Inicializadores designados" . gnu.org . Consultado el 18 de septiembre de 2019 .
- ↑ "Uso de la colección de compiladores GNU (GCC): literales compuestos" . gnu.org . Consultado el 31 de enero de 2016 .
- ↑ Ulrich Drepper (23 de octubre de 2007). "Lo que todo programador debería saber sobre la memoria" . LWN.net . Consultado el 3 de abril de 2015 .
- ↑ Especificación ISO/IEC 9899:1999, TC3 (PDF) . pág. 119, § 6.7.5.3 Declaradores de funciones (incluidos los prototipos) párr. 7.
- ↑ "¿Cuál es el propósito de la palabra clave static en el parámetro de matriz de una función como "char s[static 10 "?"].
- ↑ "¿'estático' con parámetros de matriz? ¡Oh, Dios mío!" .
- ↑ Doug Priest (1997). "Diferencias entre implementaciones de IEEE 754" .
- ↑ Jack Woehr (1 de noviembre de 1997). "Una conversación con William Kahan" .
- ↑ William Kahan (11 de junio de 1996). "El nefasto efecto de los benchmarks informáticos sobre las matemáticas aplicadas, la física y la química" (PDF) .
- ↑ William Kahan (11 de enero de 2006). "¿Qué tan inútiles son las evaluaciones sin sentido del redondeo en la computación de punto flotante?" (PDF) .
- ↑ Peter Bright (29 de junio de 2013). "C99 finalmente reconocido mientras Microsoft traza su camino hacia C++14" . Ars Technica . Consultado el 9 de enero de 2015 .
- 1 2 3 Brenner, Pat. "Novedades de Visual C++ en Visual Studio 2015" . Microsoft Developer Network . Consultado el 27 de abril de 2015 .
- ↑ "Uso del conjunto de compiladores x86 Open64" (PDF) . Developer.amd.com. Archivado (PDF) del original el 24 de enero de 2022. Consultado el 2 de marzo de 2022 .
- ↑ "cc65 - un compilador C gratuito para sistemas basados en 6502" . Consultado el 14 de septiembre de 2011 .
- ↑ "Características del intérprete C/C++ Ch C99" . SoftIntegration, Inc. 15 de febrero de 2008. Consultado el 15 de febrero de 2008 .
- ↑ "Manual del usuario del compilador Clang" . Consultado el 14 de octubre de 2017 .
- ↑ "Documentación y manual de usuario del compilador verificado CompCert C (Versión 3.10)" . 19 de noviembre de 2021. Consultado el 3 de marzo de 2022 .
- ↑ "Página principal de libfirm" . Consultado el 4 de febrero de 2014 .
- ↑ "Implementación en lenguaje C - Digital Mars" . Consultado el 14 de septiembre de 2011 .
- ↑ "Estado de las características C99 en GCC" . Free Software Foundation, Inc. 28 de julio de 2021. Consultado el 13 de agosto de 2021 .
- ↑ "Estado de las características C99 en GCC 4.6" . Free Software Foundation, Inc. 23 de mayo de 2013. Consultado el 23 de mayo de 2013 .
- ↑ "Estado de las características C99 en GCC 4.7" . Free Software Foundation, Inc. 23 de mayo de 2013. Consultado el 23 de mayo de 2013 .
- ↑ "Semántica de las matemáticas de punto flotante en GCC" . 20 de julio de 2018. Consultado el 12 de agosto de 2018 .
- ↑ "IBM C para AIX, V6.0 ahora admite el estándar C99" . 2 de julio de 2002. Consultado el 31 de enero de 2016 .
- ↑ "IBM - XL C/C++ para AIX" . Consultado el 31 de enero de 2016 .
- ↑ "Soporte de IBM Rational Logiscope para el estándar C99 - Estados Unidos" . 24 de febrero de 2012. Consultado el 31 de enero de 2016 .
- ↑ "Preguntas y respuestas de los lectores: ¿Qué hay de VC++ y C99?" . Sutter's Mill . 3 de mayo de 2012 . Consultado el 31 de enero de 2016 .
- ↑ "A.27 Uso de matrices de longitud variable C99" . Microsoft . Consultado el 31 de enero de 2016 .
- ↑ "Microsoft a los desarrolladores de C99: utilicen ISO C++" . InfoQ . Consultado el 31 de enero de 2016 .
- ↑ "Compatibilidad con la biblioteca C99 en Visual Studio 2013" . Microsoft. 19 de julio de 2013. Consultado el 31 de enero de 2016 .
- ↑ "Características, correcciones y cambios importantes de la STL de C++11/14 en VS 2013" . Blogs.msdn.com. 28 de junio de 2013. Consultado el 8 de abril de 2014 .
- ↑ "Anuncio de compatibilidad total con un preprocesador compatible con C/C++ en MSVC" . Microsoft. 27 de marzo de 2020. Consultado el 17 de septiembre de 2020 .
- ↑ "Cumplimiento de la norma C99 en Open Watcom" . Archivado del original el 3 de mayo de 2015. Consultado el 25 de septiembre de 2015 .
- ↑ "Pelles C Overview" . Enero de 2013. Archivado del original el 13 de marzo de 2022. Consultado el 2 de marzo de 2022 .
- ↑ "Página del repositorio de compiladores C portátiles" . Consultado el 21 de abril de 2026 .
- ↑ "Sun Studio 12: C Compiler 5.9 Readme" . Sun Microsystems, Inc. 31 de mayo de 2007. Consultado el 23 de septiembre de 2012 .
- ↑ "Documentación de referencia del compilador Tiny C" . Consultado el 31 de enero de 2016 .
- ↑ Según la lista de tareas pendientes del proyecto , los tipos complejos son la única característica C99 que falta. Se han añadido matrices de longitud variable en TCC 0.9.26.
- ↑ "TCC : Compilador C pequeño" . Consultado el 31 de enero de 2016 .
- ↑ "Estándares - Uso de la colección de compiladores GNU (GCC)" . Gcc.gnu.org . Consultado el 8 de abril de 2014 .
Lecturas adicionales
- N1256 (borrador final del estándar C99 más TC1, TC2, TC3); WG14; 2007. ( Versiones HTML y ASCII )
- ISO/IEC 9899:1999 (norma oficial C99); ISO ; 1999.
- Fundamentación del C99 ; WG14; 2003.
- Cheng, Harry (1 de marzo de 2002). "C99 y computación numérica" . Dr. Dobb's Journal .
- Seebach, Peter (24 de marzo de 2004). "Desarrollo de código abierto usando C99" . developerWorks . IBM .
Enlaces externos
- Documentos del Grupo de Trabajo 14 (GT14) del Lenguaje C
- Carta C9X - WG14
- Novedades en C9X
- Características de C99
- C (lenguaje de programación)
- estándares de lenguajes de programación
- Herramientas de programación Unix
- Normas IEC
- Normas ISO