stringtranslate.com

C (lenguaje de programación)

C ( pronunciado / ˈs / – como la letra c ) [6] es un lenguaje de programación informática de propósito general . Fue creado en la década de 1970 por Dennis Ritchie y sigue siendo muy utilizado e influyente. Por diseño, las características de C reflejan claramente las capacidades de las CPU de destino. Ha encontrado un uso duradero en sistemas operativos , controladores de dispositivos y pilas de protocolos , pero su uso en software de aplicaciones ha ido disminuyendo. [7] C se usa comúnmente en arquitecturas de computadoras que van desde las supercomputadoras más grandes hasta los microcontroladores y sistemas integrados más pequeños .

Ritchie desarrolló originalmente C, un sucesor del lenguaje de programación B , en los Laboratorios Bell entre 1972 y 1973 para construir utilidades que se ejecutan en Unix . Se aplicó para reimplementar el kernel del sistema operativo Unix. [8] Durante la década de 1980, C ganó popularidad gradualmente. Se ha convertido en uno de los lenguajes de programación más utilizados, [9] [10] con compiladores de C disponibles para prácticamente todas las arquitecturas informáticas y sistemas operativos modernos. El libro The C Programming Language , del que fue coautor el diseñador del lenguaje original, sirvió durante muchos años como estándar de facto para el lenguaje. [11] [1] C ha sido estandarizado desde 1989 por el Instituto Nacional Estadounidense de Estándares (ANSI) y la Organización Internacional de Normalización (ISO).

C es un lenguaje de procedimientos imperativo , que admite programación estructurada , alcance de variables léxicas y recursividad , con un sistema de tipos estáticos . Fue diseñado para ser compilado para proporcionar acceso de bajo nivel a la memoria y a construcciones de lenguaje que se asignan eficientemente a las instrucciones de la máquina , todo con un soporte de tiempo de ejecución mínimo . A pesar de sus capacidades de bajo nivel, el lenguaje fue diseñado para fomentar la programación multiplataforma. Un programa C compatible con los estándares escrito teniendo en cuenta la portabilidad se puede compilar para una amplia variedad de plataformas informáticas y sistemas operativos con pocos cambios en su código fuente.

Desde 2000, C se ha clasificado constantemente entre los dos primeros lenguajes en el índice TIOBE , una medida de la popularidad de los lenguajes de programación. [12]

Descripción general

Dennis Ritchie (derecha), el inventor del lenguaje de programación C, con Ken Thompson

C es un lenguaje procesal imperativo en la tradición ALGOL . Tiene un sistema de tipo estático . En C, todo el código ejecutable está contenido dentro de subrutinas (también llamadas "funciones", aunque no en el sentido de programación funcional ). Los parámetros de la función se pasan por valor, aunque las matrices se pasan como punteros , es decir, la dirección del primer elemento de la matriz. El paso por referencia se simula en C pasando explícitamente punteros al objeto al que se hace referencia.

El texto fuente del programa C es código de formato libre . Los puntos y coma terminan las declaraciones , mientras que las llaves se utilizan para agrupar declaraciones en bloques .

El lenguaje C también presenta las siguientes características:

Si bien C no incluye ciertas características que se encuentran en otros lenguajes (como la orientación a objetos y la recolección de basura ), estas pueden implementarse o emularse, a menudo mediante el uso de bibliotecas externas (por ejemplo, GLib Object System o el recolector de basura Boehm ).

Relaciones con otros idiomas

Muchos lenguajes posteriores han tomado prestado directa o indirectamente de C, incluidos C++ , C# , C shell de Unix , D , Go , Java , JavaScript (incluidos los transpiladores ), Julia , Limbo , LPC , Objective-C , Perl , PHP , Python , Ruby , Rust , Swift , Verilog y SystemVerilog (lenguajes de descripción de hardware). [5] Estos lenguajes han extraído muchas de sus estructuras de control y otras características básicas de C. La mayoría de ellos también expresan una sintaxis muy similar a C, y tienden a combinar la expresión reconocible y la sintaxis de declaraciones de C con sistemas de tipos subyacentes, modelos de datos. y semántica que puede ser radicalmente diferente.

Historia

Primeros desarrollos

El origen de C está estrechamente ligado al desarrollo del sistema operativo Unix , implementado originalmente en lenguaje ensamblador en un PDP-7 por Dennis Ritchie y Ken Thompson , incorporando varias ideas de sus colegas. Finalmente, decidieron portar el sistema operativo a un PDP-11 . La versión original PDP-11 de Unix también se desarrolló en lenguaje ensamblador. [8]

B

Thompson quería un lenguaje de programación para desarrollar utilidades para la nueva plataforma. Al principio intentó escribir un compilador de Fortran , pero pronto abandonó la idea. En lugar de ello, creó una versión reducida del lenguaje de programación de sistemas recientemente desarrollado llamado BCPL . La descripción oficial de BCPL no estaba disponible en ese momento [13] y Thompson modificó la sintaxis para que fuera menos prolija y similar a un ALGOL simplificado conocido como SMALGOL. [14] Thompson llamó al resultado B . [8] Describió B como "semántica BCPL con mucha sintaxis SMALGOL". [14] Al igual que BCPL, B tenía un compilador de arranque para facilitar la migración a nuevas máquinas. [14] Sin embargo, finalmente se escribieron pocas utilidades en B porque era demasiado lento y no podía aprovechar las características de PDP-11, como la direccionabilidad de bytes .

Nueva versión B y primera C

En 1971, Ritchie comenzó a mejorar B, para utilizar las características del más potente PDP-11. Una adición significativa fue un tipo de datos de carácter. A esto lo llamó Nueva B (NB). [14] Thompson comenzó a utilizar NB para escribir el kernel de Unix y sus requisitos dieron forma a la dirección del desarrollo del lenguaje. [14] [15] Hasta 1972, se agregaron tipos más ricos al lenguaje NB: NB tenía matrices de inty char. También se agregaron punteros, la capacidad de generar punteros a otros tipos, matrices de todos los tipos y tipos que se devolverán desde funciones. Las matrices dentro de las expresiones se convirtieron en punteros. Se escribió un nuevo compilador y el lenguaje pasó a llamarse C. [8]

El compilador de C y algunas utilidades creadas con él se incluyeron en la Versión 2 de Unix , que también se conoce como Research Unix . [dieciséis]

Las estructuras y la reescritura del kernel Unix

En la versión 4 de Unix , lanzada en noviembre de 1973, el kernel de Unix se reimplementó ampliamente en C. [8] Para entonces, el lenguaje C había adquirido algunas características poderosas, como los tipos.struct

El preprocesador se introdujo alrededor de 1973 a instancias de Alan Snyder y también en reconocimiento de la utilidad de los mecanismos de inclusión de archivos disponibles en BCPL y PL/I . Su versión original sólo proporcionaba archivos incluidos y reemplazos simples de cadenas: #includey #definede macros sin parámetros. Poco después, fue ampliado, principalmente por Mike Lesk y luego por John Reiser, para incorporar macros con argumentos y compilación condicional . [8]

Unix fue uno de los primeros núcleos del sistema operativo implementado en un lenguaje distinto al ensamblador . Los ejemplos anteriores incluyen el sistema Multics (que fue escrito en PL/I ) y el Programa de Control Maestro (MCP) para Burroughs B5000 (que fue escrito en ALGOL ) en 1961. Alrededor de 1977, Ritchie y Stephen C. Johnson hicieron más cambios en el lenguaje para facilitar la portabilidad del sistema operativo Unix. El compilador Portable C de Johnson sirvió como base para varias implementaciones de C en nuevas plataformas. [15]

La portada del libro The C Programming Language , primera edición, de Brian Kernighan y Dennis Ritchie

En 1978, Brian Kernighan y Dennis Ritchie publicaron la primera edición de The C Programming Language . [17] Conocido como K&R por las iniciales de sus autores, el libro sirvió durante muchos años como una especificación informal del idioma. La versión de C que describe se conoce comúnmente como " K&R C ". Como se lanzó en 1978, ahora también se lo conoce como C78 . [18] La segunda edición del libro [19] cubre el estándar ANSI C posterior , que se describe a continuación.

K&R introdujo varias características del lenguaje:

Incluso después de la publicación del estándar ANSI de 1989, durante muchos años K&R C todavía se consideraba el " mínimo común denominador " al que se restringían los programadores de C cuando se deseaba la máxima portabilidad, ya que muchos compiladores más antiguos todavía estaban en uso y porque K&R estaba cuidadosamente escrito. El código C también puede ser el estándar C legal.

En las primeras versiones de C, sólo las funciones que devuelven tipos distintos de intdeben declararse si se utilizan antes de la definición de la función; Se suponía que las funciones utilizadas sin declaración previa devolvían el tipo int.

Por ejemplo:

largo alguna_función (); /* Esta es una declaración de función, por lo que el compilador puede conocer el nombre y el tipo de retorno de esta función. */ /* int */ otra_función (); /* Otra declaración de función. Como se trata de una versión anterior de C, aquí hay un tipo 'int' implícito. Un comentario muestra dónde se requeriría el especificador de tipo 'int' explícito en versiones posteriores. */    /* int */ call_function () /* Esta es una definición de función, incluido el cuerpo del código que sigue entre { llaves }. Debido a que no se especifica ningún tipo de retorno, la función devuelve implícitamente un 'int' en esta primera versión de C. */ { long test1 ; registrar /* int */ prueba2 ; /* Nuevamente, tenga en cuenta que aquí no se requiere 'int'. El especificador de tipo 'int' */ /* en el comentario sería necesario en versiones posteriores de C. */ /* La palabra clave 'register' indica al compilador que esta variable debería */ /* idealmente almacenarse en un registro como opuesto a dentro del marco de la pila. */ prueba1 = alguna_función (); si ( prueba1 > 1 ) prueba2 = 0 ; else prueba2 = otra_función (); devolver prueba2 ; }                           

Los intespecificadores de tipo comentados podrían omitirse en K&R C, pero son obligatorios en estándares posteriores.

Dado que las declaraciones de funciones de K&R no incluían ninguna información sobre los argumentos de la función, no se realizaron comprobaciones de los tipos de parámetros de la función , aunque algunos compiladores emitirían un mensaje de advertencia si se llamaba a una función local con un número incorrecto de argumentos o si se realizaban llamadas diferentes a una función externa. Utilizaron diferentes números o tipos de argumentos. Se desarrollaron herramientas independientes, como la utilidad lint de Unix, que (entre otras cosas) podían comprobar la coherencia del uso de funciones en múltiples archivos fuente.

En los años posteriores a la publicación de K&R C, se agregaron varias características al lenguaje, respaldadas por compiladores de AT&T (en particular PCC [20] ) y algunos otros proveedores. Estos incluyeron:

La gran cantidad de extensiones y la falta de acuerdo sobre una biblioteca estándar , junto con la popularidad del lenguaje y el hecho de que ni siquiera los compiladores de Unix implementaron con precisión la especificación K&R, llevaron a la necesidad de estandarización. [ cita necesaria ]

ANSI C e ISO C

A finales de los años 1970 y 1980, se implementaron versiones de C para una amplia variedad de computadoras mainframe , minicomputadoras y microcomputadoras , incluida la IBM PC , a medida que su popularidad comenzó a aumentar significativamente.

En 1983, el Instituto Nacional Estadounidense de Estándares (ANSI) formó un comité, X3J11, para establecer una especificación estándar de C. X3J11 basó el estándar C en la implementación de Unix; sin embargo, la parte no portátil de la biblioteca Unix C se entregó al grupo de trabajo 1003 de IEEE para convertirse en la base del estándar POSIX de 1988 . En 1989, el estándar C fue ratificado como ANSI X3.159-1989 "Lenguaje de programación C". Esta versión del lenguaje a menudo se denomina ANSI C , Estándar C o, a veces, C89.

En 1990, la Organización Internacional de Normalización (ISO) adoptó el estándar ANSI C (con cambios de formato) como ISO/IEC 9899:1990, que a veces se denomina C90. Por tanto, los términos "C89" y "C90" se refieren al mismo lenguaje de programación.

ANSI, al igual que otros organismos nacionales de normalización, ya no desarrolla el estándar C de forma independiente, sino que se remite al estándar C internacional, mantenido por el grupo de trabajo ISO/IEC JTC1/SC22 /WG14. La adopción nacional de una actualización del estándar internacional generalmente ocurre dentro del año posterior a la publicación de ISO.

Uno de los objetivos del proceso de estandarización de C fue producir un superconjunto de K&R C, incorporando muchas de las características no oficiales introducidas posteriormente. El comité de estándares también incluyó varias características adicionales, como prototipos de funciones (tomado de C++), voidpunteros, soporte para conjuntos de caracteres y configuraciones regionales internacionales y mejoras en el preprocesador. Aunque la sintaxis para las declaraciones de parámetros se aumentó para incluir el estilo utilizado en C++, la interfaz K&R siguió estando permitida por compatibilidad con el código fuente existente.

C89 es compatible con los compiladores de C actuales y la mayoría del código C moderno se basa en él. Cualquier programa escrito únicamente en el estándar C y sin suposiciones dependientes del hardware se ejecutará correctamente en cualquier plataforma con una implementación conforme a C, dentro de sus límites de recursos. Sin tales precauciones, los programas pueden compilarse sólo en una determinada plataforma o con un compilador particular, debido, por ejemplo, al uso de bibliotecas no estándar, como las bibliotecas GUI , o a la dependencia de atributos específicos del compilador o de la plataforma, como como el tamaño exacto de los tipos de datos y el endianidad de bytes .

En los casos en los que el código debe ser compilable mediante compiladores que cumplan con el estándar o basados ​​en K&R C, la __STDC__macro se puede usar para dividir el código en secciones Estándar y K&R para evitar el uso en un compilador basado en K&R C de características disponibles solo en Estándar. C.

Después del proceso de estandarización ANSI/ISO, la especificación del lenguaje C permaneció relativamente estática durante varios años. En 1995, se publicó la Enmienda Normativa 1 al estándar 1990 C (ISO/IEC 9899/AMD1:1995, conocido informalmente como C95), para corregir algunos detalles y agregar un soporte más amplio para juegos de caracteres internacionales. [21]

C99

El estándar C fue revisado nuevamente a fines de la década de 1990, lo que llevó a la publicación de ISO/IEC 9899:1999 en 1999, que comúnmente se conoce como " C99 ". Desde entonces ha sido modificado tres veces por Corrigenda Técnica. [22]

C99 introdujo varias características nuevas, incluidas funciones en línea , varios tipos de datos nuevos (incluido long long intun complextipo para representar números complejos ), matrices de longitud variable y miembros de matriz flexibles , soporte mejorado para punto flotante IEEE 754 , soporte para macros variadas (macros de variable arity ) y soporte para comentarios de una línea que comienzan con //, como en BCPL o C++. Muchos de ellos ya se habían implementado como extensiones en varios compiladores de C.

C99 es en su mayor parte compatible con versiones anteriores de C90, pero es más estricto en algunos aspectos; en particular, una declaración que carece de un especificador de tipo ya no se intasume implícitamente. __STDC_VERSION__Se define una macro estándar con un valor 199901Lpara indicar que la compatibilidad con C99 está disponible. GCC , Solaris Studio y otros compiladores de C ahora [ ¿cuándo? ] admite muchas o todas las nuevas funciones de C99. Sin embargo, el compilador de C en Microsoft Visual C++ implementa el estándar C89 y aquellas partes de C99 que son necesarias para la compatibilidad con C++11 . [23] [ necesita actualización ]

Además, el estándar C99 requiere soporte para identificadores que usan Unicode en forma de caracteres de escape (por ejemplo, \u0040o \U0001f431) y sugiere soporte para nombres Unicode sin formato.

C11

En 2007, se inició el trabajo en otra revisión del estándar C, informalmente llamado "C1X" hasta su publicación oficial de ISO/IEC 9899:2011 el 8 de diciembre de 2011. El comité de estándares C adoptó pautas para limitar la adopción de nuevas características que no habían sido probadas por implementaciones existentes.

El estándar C11 agrega numerosas características nuevas a C y a la biblioteca, incluidas macros genéricas de tipo, estructuras anónimas, compatibilidad mejorada con Unicode, operaciones atómicas, subprocesos múltiples y funciones con verificación de límites. También hace que algunas partes de la biblioteca C99 existente sean opcionales y mejora la compatibilidad con C++. La macro estándar __STDC_VERSION__se define para 201112Lindicar que el soporte C11 está disponible.

C17

Publicado en junio de 2018 como ISO/IEC 9899:2018, C17 es el estándar actual para el lenguaje de programación C. No introduce nuevas características de lenguaje, solo correcciones técnicas y aclaraciones de defectos en C11. La macro estándar __STDC_VERSION__se define para 201710Lindicar que la compatibilidad con C17 está disponible.

C23

C23 es el nombre informal de la siguiente revisión principal del estándar del lenguaje C (después de C17). Fue conocido informalmente como "C2X" durante la mayor parte de su desarrollo. Se espera que C23 se publique a principios de 2024 como ISO/IEC 9899:2024. [24] La macro estándar __STDC_VERSION__se define para 202311Lindicar que el soporte C23 está disponible.

C2Y

C2Y es un nombre informal temporal para la próxima revisión importante del estándar del lenguaje C, después de C23 (C2X), que se espera que se publique más adelante en la década de 2020 , según los dos en "C2Y". En febrero de 2024, el grupo de trabajo ISO/IEC JTC1/SC22 /WG14 publicó un borrador de trabajo inicial de C2Y como N3220 . [25]

C incrustado

Históricamente, la programación en C integrada requiere extensiones no estándar del lenguaje C para admitir características exóticas como la aritmética de punto fijo , múltiples bancos de memoria distintos y operaciones básicas de E/S.

En 2008, el Comité de Estándares C publicó un informe técnico ampliando el lenguaje C [26] para abordar estos problemas proporcionando un estándar común al que deben adherirse todas las implementaciones. Incluye una serie de características que no están disponibles en C normal, como aritmética de punto fijo , espacios de direcciones con nombre y direccionamiento básico de hardware de E/S.

Sintaxis

C tiene una gramática formal especificada por el estándar C. [27] Los finales de línea generalmente no son significativos en C; sin embargo, los límites de las líneas tienen importancia durante la fase de preprocesamiento. Los comentarios pueden aparecer entre los delimitadores /*y */, o (desde C99) después //hasta el final de la línea. Los comentarios delimitados por /*y */no se anidan, y estas secuencias de caracteres no se interpretan como delimitadores de comentarios si aparecen dentro de cadenas o caracteres literales. [28]

Los archivos fuente C contienen declaraciones y definiciones de funciones. Las definiciones de funciones, a su vez, contienen declaraciones y enunciados . Las declaraciones definen nuevos tipos usando palabras clave como struct, uniony enum, o asignan tipos y tal vez reservan almacenamiento para nuevas variables, generalmente escribiendo el tipo seguido del nombre de la variable. Palabras clave como chary intespecifican tipos integrados. Las secciones de código están encerradas entre llaves ( {y }, a veces llamadas "llaves") para limitar el alcance de las declaraciones y actuar como una declaración única para las estructuras de control.

Como lenguaje imperativo, C utiliza declaraciones para especificar acciones. La declaración más común es una declaración de expresión , que consta de una expresión a evaluar, seguida de un punto y coma; como efecto secundario de la evaluación, se pueden llamar funciones y se pueden asignar nuevos valores a las variables. Para modificar la ejecución secuencial normal de declaraciones, C proporciona varias declaraciones de flujo de control identificadas por palabras clave reservadas. La programación estructurada está respaldada por if... [ else] ejecución condicional y por do... while, whiley forejecución iterativa (bucle). La fordeclaración tiene expresiones de inicialización, prueba y reinicialización separadas, cualquiera o todas las cuales pueden omitirse. breaky continuese puede utilizar dentro del bucle. Break se usa para salir de la declaración de bucle envolvente más interna y continue se usa para saltar a su reinicialización. También hay una gotodeclaración no estructurada que va directamente a la etiqueta designada dentro de la función. switchselecciona a casepara ejecutar en función del valor de una expresión entera. A diferencia de muchos otros lenguajes, control-flow pasará al siguiente casea menos que finalice con un archivo break.

Las expresiones pueden utilizar una variedad de operadores integrados y pueden contener llamadas a funciones. No se especifica el orden en el que se evalúan los argumentos de las funciones y los operandos de la mayoría de los operadores. Las evaluaciones pueden incluso estar intercaladas. Sin embargo, todos los efectos secundarios (incluido el almacenamiento en variables) ocurrirán antes del siguiente " punto de secuencia "; Los puntos de secuencia incluyen el final de cada declaración de expresión y la entrada y el retorno de cada llamada de función. Los puntos de secuencia también ocurren durante la evaluación de expresiones que contienen ciertos operadores ( &&, y el operador de coma|| ) . Esto permite un alto grado de optimización del código objeto por parte del compilador, pero requiere que los programadores de C tengan más cuidado para obtener resultados confiables que el necesario para otros lenguajes de programación.?:

Kernighan y Ritchie dicen en la Introducción al lenguaje de programación C : "C, como cualquier otro lenguaje, tiene sus defectos. Algunos de los operadores tienen una precedencia incorrecta; algunas partes de la sintaxis podrían ser mejores". [29] El estándar C no intentó corregir muchos de estos defectos, debido al impacto de tales cambios en el software ya existente.

Conjunto de caracteres

El conjunto de caracteres fuente C básico incluye los siguientes caracteres:

Nueva línea indica el final de una línea de texto; No es necesario que corresponda a un único carácter real, aunque por conveniencia C lo trata como tal.

Se pueden usar caracteres codificados de varios bytes adicionales en literales de cadena, pero no son completamente portátiles . El último estándar C ( C11 ) permite incrustar caracteres Unicode multinacionales de forma portátil dentro del texto fuente C mediante el uso \uXXXXo \UXXXXXXXXcodificación (donde Xdenota un carácter hexadecimal), aunque esta característica aún no está ampliamente implementada.

El conjunto de caracteres de ejecución básico de C contiene los mismos caracteres, junto con representaciones de alerta , retroceso y retorno de carro . El soporte en tiempo de ejecución para conjuntos de caracteres extendidos ha aumentado con cada revisión del estándar C.

Palabras reservadas

Las siguientes palabras reservadas distinguen entre mayúsculas y minúsculas .

C89 tiene 32 palabras reservadas, también conocidas como palabras clave, que son palabras que no se pueden utilizar para ningún otro propósito que no sean aquellos para los que están predefinidas:

C99 reservó cinco palabras más: (‡ es un alias de ortografía alternativo para una palabra clave C23)

C11 reservó siete palabras más: [30] (‡ es un alias de ortografía alternativo para una palabra clave C23)

C23 reservó quince palabras más:

La mayoría de las palabras recientemente reservadas comienzan con un guión bajo seguido de una letra mayúscula, porque los identificadores de esa forma estaban previamente reservados por el estándar C para uso exclusivo de implementaciones. Dado que el código fuente del programa existente no debería haber utilizado estos identificadores, no se vería afectado cuando las implementaciones de C comenzaran a admitir estas extensiones del lenguaje de programación. Algunos encabezados estándar definen sinónimos más convenientes para identificadores subrayados. Algunas de esas palabras se agregaron como palabras clave con su ortografía convencional en C23 y se eliminaron las macros correspondientes.

Antes del C89, entryestaba reservada como palabra clave. En la segunda edición de su libro The C Programming Language , que describe lo que se conoció como C89, Kernighan y Ritchie escribieron: "La... [palabra clave] entry, anteriormente reservada pero nunca utilizada, ya no está reservada". y " entrySe retira la palabra clave que nació muerta". [31]

Operadores

C admite un amplio conjunto de operadores , que son símbolos utilizados dentro de una expresión para especificar las manipulaciones que se realizarán mientras se evalúa esa expresión. C tiene operadores para:

C usa el operador =(usado en matemáticas para expresar igualdad) para indicar asignación, siguiendo el precedente de Fortran y PL/I , pero a diferencia de ALGOL y sus derivados. C usa el operador ==para probar la igualdad. La similitud entre estos dos operadores (asignación e igualdad) puede resultar en el uso accidental de uno en lugar del otro y, en muchos casos, el error no produce un mensaje de error (aunque algunos compiladores generan advertencias). Por ejemplo, la expresión condicional if (a == b + 1)podría escribirse por error como if (a = b + 1), que se evaluará como verdadera si ano es cero después de la asignación. [32]

La precedencia del operador C no siempre es intuitiva. Por ejemplo, el operador ==se vincula más estrechamente que (se ejecuta antes) los operadores &(Y bit a bit) y |(OR bit a bit) en expresiones como x & 1 == 0, que deben escribirse como (x & 1) == 0si esa fuera la intención del codificador. [33]

Ejemplo de "Hola mundo"

"¡Hola Mundo!" programa de Brian Kernighan (1978)

El ejemplo " hola, mundo ", que apareció en la primera edición de K&R , se ha convertido en el modelo para un programa introductorio en la mayoría de los libros de texto de programación. El programa imprime "hola, mundo" en la salida estándar , que suele ser una terminal o una pantalla.

La versión original era: [34]

main () { printf ( "hola, mundo \n " ); } 

Un programa "hola, mundo" que cumple con el estándar es: [a]

#incluir <stdio.h> int main ( void ) { printf ( "hola, mundo \n " ); }  

La primera línea del programa contiene una directiva de preprocesamiento , indicada por #include. Esto hace que el compilador reemplace esa línea con el texto completo del stdio.hencabezado estándar, que contiene declaraciones para funciones estándar de entrada y salida como printfy scanf. Los corchetes angulares que lo rodean stdio.hindican que stdio.hse puede ubicar usando una estrategia de búsqueda que prefiere los encabezados proporcionados con el compilador a otros encabezados que tienen el mismo nombre, a diferencia de las comillas dobles que generalmente incluyen archivos de encabezado locales o específicos del proyecto.

La siguiente línea indica que mainse está definiendo una función nombrada. La mainfunción tiene un propósito especial en programas C; el entorno de ejecución llama a la mainfunción para comenzar la ejecución del programa. El especificador de tipo intindica que el valor que se devuelve al invocador (en este caso, el entorno de ejecución) como resultado de evaluar la mainfunción es un número entero. La palabra clave voidcomo lista de parámetros indica que esta función no acepta argumentos. [b]

La llave de apertura indica el comienzo de la definición de la mainfunción.

La siguiente línea llama (desvía la ejecución a) una función denominada printf, que en este caso se suministra desde una biblioteca del sistema . En esta llamada, a la printffunción se le pasa (se le proporciona) un único argumento, la dirección del primer carácter de la cadena literal "hello, world\n" . El literal de cadena es una matriz sin nombre con elementos de tipo char, configurada automáticamente por el compilador con un carácter final NULL (valor ASCII 0) para marcar el final de la matriz (para printfconocer la longitud de la cadena). El carácter NULL puede También debe escribirse como una secuencia de escape , escrita como \0. Es \nuna secuencia de escape que C traduce a un carácter de nueva línea , que en la salida significa el final de la línea actual. El valor de retorno de la printffunción es de tipo int, pero se descarta silenciosamente ya que no se utiliza. (Un programa más cuidadoso podría probar el valor de retorno para determinar si la printffunción tuvo éxito o no). El punto y coma ;termina la declaración.

La llave de cierre indica el final del código de la mainfunción. Según la especificación C99 y posteriores, la mainfunción, a diferencia de cualquier otra función, devolverá implícitamente un valor de 0al alcanzar el }que finaliza la función. (Anteriormente return 0;se requería una declaración explícita). El sistema de ejecución lo interpreta como un código de salida que indica una ejecución exitosa. [35]

Tipos de datos

El sistema de tipos en C es estático y débilmente tipado , lo que lo hace similar al sistema de tipos de los descendientes de ALGOL como Pascal . [36] Hay tipos integrados para números enteros de varios tamaños, tanto con signo como sin signo, números de punto flotante y tipos enumerados ( enum). El tipo entero charse utiliza a menudo para caracteres de un solo byte. C99 agregó un tipo de datos booleano . También hay tipos derivados que incluyen matrices , punteros , registros ( struct) y uniones ( union).

C se utiliza a menudo en la programación de sistemas de bajo nivel donde pueden ser necesarios escapes del sistema de tipos. El compilador intenta garantizar la corrección del tipo de la mayoría de las expresiones, pero el programador puede anular las comprobaciones de varias maneras, ya sea usando una conversión de tipo para convertir explícitamente un valor de un tipo a otro, o usando punteros o uniones para reinterpretar los bits subyacentes. de un objeto de datos de alguna otra manera.

Algunos encuentran que la sintaxis de declaración de C no es intuitiva, particularmente para los punteros de función . (La idea de Ritchie era declarar identificadores en contextos que se asemejaran a su uso: " la declaración refleja el uso "). [37]

Las conversiones aritméticas habituales de C permiten generar código eficiente, pero a veces pueden producir resultados inesperados. Por ejemplo, una comparación de enteros con y sin signo de igual ancho requiere una conversión del valor con signo a sin signo. Esto puede generar resultados inesperados si el valor firmado es negativo.

Consejos

C admite el uso de punteros , un tipo de referencia que registra la dirección o ubicación de un objeto o función en la memoria. Se puede eliminar la referencia a los punteros para acceder a los datos almacenados en la dirección a la que se apunta o para invocar una función a la que se apunta. Los punteros se pueden manipular mediante asignación o aritmética de punteros . La representación en tiempo de ejecución de un valor de puntero suele ser una dirección de memoria sin procesar (quizás aumentada por un campo de desplazamiento dentro de la palabra), pero dado que el tipo de un puntero incluye el tipo de objeto al que apunta, se pueden verificar el tipo de expresiones que incluyen punteros. en tiempo de compilación. La aritmética de punteros se escala automáticamente según el tamaño del tipo de datos al que apunta.

Los punteros se utilizan para muchos propósitos en C. Las cadenas de texto se manipulan comúnmente utilizando punteros en matrices de caracteres. La asignación de memoria dinámica se realiza mediante punteros; el resultado de a mallocgeneralmente se convierte al tipo de datos que se van a almacenar. Muchos tipos de datos, como los árboles , se implementan comúnmente como structobjetos asignados dinámicamente y vinculados entre sí mediante punteros. Los punteros a otros punteros se utilizan a menudo en matrices multidimensionales y matrices de structobjetos. Los punteros a funciones ( punteros de función ) son útiles para pasar funciones como argumentos a funciones de orden superior (como qsort o bsearch ), en tablas de distribución o como devoluciones de llamada a controladores de eventos . [35]

Un valor de puntero nulo apunta explícitamente a una ubicación no válida. La eliminación de la referencia a un valor de puntero nulo no está definida, lo que a menudo resulta en un error de segmentación . Los valores de puntero nulos son útiles para indicar casos especiales, como que no hay un puntero "siguiente" en el nodo final de una lista vinculada , o como una indicación de error de funciones que devuelven punteros. En contextos apropiados en el código fuente, como para asignar a una variable de puntero, una constante de puntero nulo se puede escribir como 0, con o sin conversión explícita a un tipo de puntero, como la NULLmacro definida por varios encabezados estándar o, desde C23 con la constante nullptr. En contextos condicionales, los valores de puntero nulos se evalúan como falso, mientras que todos los demás valores de puntero se evalúan como verdadero.

Los punteros vacíos ( void *) apuntan a objetos de tipo no especificado y, por lo tanto, pueden usarse como punteros de datos "genéricos". Dado que se desconoce el tamaño y el tipo del objeto al que se apunta, no se puede desreferenciar los punteros vacíos, ni se permite la aritmética de punteros sobre ellos, aunque se pueden convertir fácilmente (y en muchos contextos se hace implícitamente) hacia y desde cualquier otro puntero de objeto. tipo. [35]

El uso descuidado de los punteros es potencialmente peligroso. Como normalmente no están marcadas, se puede hacer que una variable de puntero apunte a cualquier ubicación arbitraria, lo que puede provocar efectos no deseados. Aunque los punteros utilizados correctamente apuntan a lugares seguros, se puede hacer que apunten a lugares inseguros utilizando aritmética de punteros no válida ; los objetos a los que apuntan pueden seguir utilizándose después de la desasignación ( punteros colgantes ); se pueden utilizar sin haber sido inicializados ( punteros salvajes ); o se les puede asignar directamente un valor inseguro mediante una conversión, unión o mediante otro puntero corrupto. En general, C es permisivo al permitir la manipulación y conversión entre tipos de punteros, aunque los compiladores suelen ofrecer opciones para varios niveles de verificación. Algunos otros lenguajes de programación abordan estos problemas utilizando tipos de referencia más restrictivos .

matrices

Los tipos de matrices en C tradicionalmente tienen un tamaño fijo y estático especificado en el momento de la compilación. El estándar C99 más reciente también permite una forma de matrices de longitud variable. Sin embargo, también es posible asignar un bloque de memoria (de tamaño arbitrario) en tiempo de ejecución, utilizando la mallocfunción de la biblioteca estándar, y tratarlo como una matriz.

Dado que siempre se accede a las matrices (en efecto) a través de punteros, los accesos a las matrices generalmente no se verifican con el tamaño de la matriz subyacente, aunque algunos compiladores pueden proporcionar verificación de límites como una opción. [38] [39] Por lo tanto, las violaciones de los límites de la matriz son posibles y pueden tener diversas repercusiones, incluidos accesos ilegales a la memoria, corrupción de datos, desbordamientos del búfer y excepciones de tiempo de ejecución.

C no tiene una disposición especial para declarar matrices multidimensionales , sino que se basa en la recursividad dentro del sistema de tipos para declarar matrices de matrices, lo que efectivamente logra lo mismo. Se puede considerar que los valores de índice de la "matriz multidimensional" resultante aumentan en el orden de las filas principales . Las matrices multidimensionales se utilizan comúnmente en algoritmos numéricos (principalmente del álgebra lineal aplicada ) para almacenar matrices. La estructura de la matriz C se adapta bien a esta tarea particular. Sin embargo, en las primeras versiones de C, los límites de la matriz deben ser valores fijos conocidos o pasarse explícitamente a cualquier subrutina que los requiera, y no se puede acceder a matrices de matrices de tamaño dinámico mediante indexación doble. (Una solución para esto fue asignar a la matriz un "vector de fila" adicional de punteros a las columnas). C99 introdujo "matrices de longitud variable" que solucionan este problema.

El siguiente ejemplo que utiliza C moderno (C99 o posterior) muestra la asignación de una matriz bidimensional en el montón y el uso de indexación de matrices multidimensionales para los accesos (que puede utilizar la verificación de límites en muchos compiladores de C):

int func ( int N , int M ) { float ( * p ) [ N ] [ M ] = malloc ( tamaño de * p ); si ( p == 0 ) devuelve -1 ; para ( int i = 0 ; i < N ; i ++ ) para ( int j = 0 ; j < M ; j ++ ) ( * p )[ i ][ j ] = i + j ; print_array ( N , M , p ); libre ( pag ); devolver 1 ; }                                            

Y aquí hay una implementación similar usando la función Auto VLA de C99 : [c]

int func ( int N , int M ) { // Precaución: se deben realizar comprobaciones para garantizar que N*M*sizeof(float) NO exceda las limitaciones para los VLA automáticos y esté dentro del tamaño disponible de la pila. flotador p [ N ][ M ]; // el VLA automático se mantiene en la pila y se dimensiona cuando se invoca la función for ( int i = 0 ; i < N ; i ++ ) for ( int j = 0 ; j < M ; j ++ ) p [ i ][ j ] = yo + j ; print_array ( N , M , p ); // no es necesario liberar(p) ya que desaparecerá cuando la función salga, junto con el resto del marco de la pila return 1 ; }                                     

Intercambiabilidad matriz-puntero

La notación de subíndice x[i](donde xdesigna un puntero) es azúcar sintáctica para *(x+i). [40] Aprovechando el conocimiento del compilador sobre el tipo de puntero, la dirección a la que x + iapunta no es la dirección base (señalada por x) incrementada en ibytes, sino que se define como la dirección base incrementada por imultiplicada por el tamaño de un elemento que xapunta. Por tanto, x[i]designa el i+1décimo elemento de la matriz.

Además, en la mayoría de los contextos de expresión (una excepción notable es el operando de sizeof), una expresión de tipo matriz se convierte automáticamente en un puntero al primer elemento de la matriz. Esto implica que una matriz nunca se copia en su totalidad cuando se nombra como argumento de una función, sino que solo se pasa la dirección de su primer elemento. Por lo tanto, aunque las llamadas a funciones en C usan semántica de paso por valor , las matrices en realidad se pasan por referencia .

El tamaño total de una matriz xse puede determinar aplicándolo sizeofa una expresión de tipo matriz. El tamaño de un elemento se puede determinar aplicando el operador sizeofa cualquier elemento desreferenciado de una matriz A, como en n = sizeof A[0]. Por lo tanto, el número de elementos en una matriz declarada Ase puede determinar como sizeof A / sizeof A[0]. Tenga en cuenta que si solo está disponible un puntero al primer elemento, como suele ser el caso en el código C debido a la conversión automática descrita anteriormente, se pierde la información sobre el tipo completo de la matriz y su longitud.

Gestión de la memoria

Una de las funciones más importantes de un lenguaje de programación es proporcionar facilidades para administrar la memoria y los objetos que se almacenan en la memoria. C proporciona tres formas principales de asignar memoria para objetos: [35]

Estos tres enfoques son apropiados en diferentes situaciones y tienen diversas compensaciones. Por ejemplo, la asignación de memoria estática tiene poca sobrecarga de asignación, la asignación automática puede implicar una sobrecarga ligeramente mayor y la asignación de memoria dinámica puede potencialmente tener una gran sobrecarga tanto para la asignación como para la desasignación. La naturaleza persistente de los objetos estáticos es útil para mantener información de estado entre llamadas a funciones, la asignación automática es fácil de usar, pero el espacio de la pila suele ser mucho más limitado y transitorio que la memoria estática o el espacio del montón, y la asignación de memoria dinámica permite una asignación conveniente de objetos cuyos El tamaño se conoce sólo en tiempo de ejecución. La mayoría de los programas en C hacen un uso extensivo de los tres.

Cuando es posible, la asignación automática o estática suele ser la más sencilla porque el compilador gestiona el almacenamiento, lo que libera al programador de la tarea potencialmente propensa a errores de asignar y liberar almacenamiento manualmente. Sin embargo, muchas estructuras de datos pueden cambiar de tamaño en tiempo de ejecución y, dado que las asignaciones estáticas (y las asignaciones automáticas anteriores a C99) deben tener un tamaño fijo en tiempo de compilación, hay muchas situaciones en las que la asignación dinámica es necesaria. [35] Antes del estándar C99, las matrices de tamaño variable eran un ejemplo común de esto. (Consulte el artículo sobre mallocpara ver un ejemplo de matrices asignadas dinámicamente). A diferencia de la asignación automática, que puede fallar en tiempo de ejecución con consecuencias incontroladas, las funciones de asignación dinámica devuelven una indicación (en forma de un valor de puntero nulo) cuando el almacenamiento requerido no puede ser asignado. (El vinculador o el cargador generalmente detecta la asignación estática que es demasiado grande , incluso antes de que el programa pueda comenzar la ejecución).

A menos que se especifique lo contrario, los objetos estáticos contienen valores de puntero cero o nulos al iniciar el programa. Los objetos asignados automática y dinámicamente se inicializan sólo si se especifica explícitamente un valor inicial; de lo contrario, inicialmente tienen valores indeterminados (normalmente, cualquier patrón de bits que esté presente en el almacenamiento , que podría ni siquiera representar un valor válido para ese tipo). Si el programa intenta acceder a un valor no inicializado, los resultados no están definidos. Muchos compiladores modernos intentan detectar y advertir sobre este problema, pero pueden producirse tanto falsos positivos como falsos negativos .

La asignación de memoria dinámica debe sincronizarse con su uso real en cualquier programa para poder reutilizarse tanto como sea posible. Por ejemplo, si el único puntero a una asignación de memoria de montón sale del alcance o se sobrescribe su valor antes de desasignarlo explícitamente, entonces esa memoria no se puede recuperar para su reutilización posterior y esencialmente se pierde para el programa, un fenómeno conocido como memoria. filtración . Por el contrario, es posible liberar memoria, pero se hace referencia a ella posteriormente, lo que genera resultados impredecibles. Normalmente, los síntomas de falla aparecen en una parte del programa que no está relacionada con el código que causa el error, lo que dificulta el diagnóstico de la falla. Estos problemas mejoran en los lenguajes con recolección automática de basura .

Bibliotecas

El lenguaje de programación C utiliza bibliotecas como método principal de extensión. En C, una biblioteca es un conjunto de funciones contenidas en un único archivo "archivado". Cada biblioteca suele tener un archivo de encabezado , que contiene los prototipos de las funciones contenidas en la biblioteca que puede utilizar un programa, y ​​declaraciones de tipos de datos especiales y símbolos de macro utilizados con estas funciones. Para que un programa utilice una biblioteca, debe incluir el archivo de encabezado de la biblioteca y la biblioteca debe estar vinculada con el programa, lo que en muchos casos requiere indicadores del compilador (p. ej. -lm, abreviatura de "vincular la biblioteca matemática"). [35]

La biblioteca C más común es la biblioteca estándar C , que está especificada por los estándares ISO y ANSI C y viene con cada implementación de C (las implementaciones dirigidas a entornos limitados, como sistemas integrados, pueden proporcionar solo un subconjunto de la biblioteca estándar). Esta biblioteca admite entrada y salida de flujo, asignación de memoria, matemáticas, cadenas de caracteres y valores de tiempo. Varios encabezados estándar separados (por ejemplo, stdio.h) especifican las interfaces para estas y otras funciones de biblioteca estándar.

Otro conjunto común de funciones de la biblioteca C son las utilizadas por aplicaciones específicamente destinadas a Unix y sistemas similares a Unix , especialmente funciones que proporcionan una interfaz para el kernel . Estas funciones se detallan en varios estándares como POSIX y la Especificación Única UNIX .

Dado que muchos programas se han escrito en C, existe una amplia variedad de otras bibliotecas disponibles. Las bibliotecas suelen escribirse en C porque los compiladores de C generan código objeto eficiente ; Luego, los programadores crean interfaces para la biblioteca para que las rutinas puedan usarse desde lenguajes de nivel superior como Java , Perl y Python . [35]

Manejo de archivos y transmisiones

La entrada y salida de archivos (E/S) no forma parte del lenguaje C en sí, sino que es manejada por bibliotecas (como la biblioteca estándar de C) y sus archivos de encabezado asociados (por ejemplo, stdio.h). El manejo de archivos generalmente se implementa a través de E/S de alto nivel que funciona a través de transmisiones . Desde esta perspectiva, una secuencia es un flujo de datos independiente de los dispositivos, mientras que un archivo es un dispositivo concreto. La E/S de alto nivel se realiza mediante la asociación de una secuencia a un archivo. En la biblioteca estándar de C, se utiliza temporalmente un búfer (un área de memoria o cola) para almacenar datos antes de enviarlos al destino final. Esto reduce el tiempo de espera de dispositivos más lentos, por ejemplo un disco duro o una unidad de estado sólido . Las funciones de E/S de bajo nivel no forman parte de la biblioteca C estándar [ se necesita aclaración ], pero generalmente forman parte de la programación "bare metal" (programación que es independiente de cualquier sistema operativo , como la mayoría de la programación integrada ). Con pocas excepciones, las implementaciones incluyen E/S de bajo nivel.

Herramientas del lenguaje

Se han desarrollado varias herramientas para ayudar a los programadores de C a encontrar y corregir declaraciones con comportamiento indefinido o expresiones posiblemente erróneas, con mayor rigor que el proporcionado por el compilador. La pelusa de la herramienta fue la primera, y dio lugar a muchas otras.

La verificación y auditoría automatizadas del código fuente son beneficiosas en cualquier lenguaje y para C existen muchas herramientas de este tipo, como Lint . Una práctica común es utilizar Lint para detectar código cuestionable cuando se escribe un programa por primera vez. Una vez que un programa pasa Lint, se compila utilizando el compilador de C. Además, muchos compiladores pueden opcionalmente advertir sobre construcciones sintácticamente válidas que probablemente sean errores. MISRA C es un conjunto patentado de pautas para evitar este tipo de código cuestionable, desarrollado para sistemas integrados. [41]

También existen compiladores, bibliotecas y mecanismos a nivel de sistema operativo para realizar acciones que no son una parte estándar de C, como la verificación de límites de matrices, la detección de desbordamiento del búfer , la serialización , el seguimiento dinámico de la memoria y la recolección automática de basura .

Herramientas como Purify o Valgrind y la vinculación con bibliotecas que contienen versiones especiales de las funciones de asignación de memoria pueden ayudar a descubrir errores de tiempo de ejecución en el uso de la memoria. [42] [43]

Usos

Justificación del uso en la programación de sistemas.

Algún software escrito en C

C se usa ampliamente para la programación de sistemas en la implementación de sistemas operativos y aplicaciones de sistemas integrados . [44] Esto se debe a varias razones:

Utilizado para bibliotecas computacionalmente intensivas

C permite a los programadores crear implementaciones eficientes de algoritmos y estructuras de datos, porque la capa de abstracción del hardware es delgada y su sobrecarga es baja, un criterio importante para programas computacionalmente intensivos. Por ejemplo, la biblioteca aritmética de precisión múltiple GNU , la biblioteca científica GNU , Mathematica y MATLAB están escritas total o parcialmente en C. Muchos lenguajes admiten la llamada a funciones de biblioteca en C; por ejemplo, el marco basado en Python NumPy usa C para la alta -aspectos de rendimiento y de interacción con el hardware.

C como lenguaje intermedio

A veces, C se utiliza como lenguaje intermedio en implementaciones de otros lenguajes. Este enfoque puede utilizarse por motivos de portabilidad o conveniencia; Al utilizar C como lenguaje intermedio, no son necesarios generadores de código adicionales específicos de la máquina. C tiene algunas características, como directivas de preprocesador de número de línea y comas superfluas opcionales al final de las listas de inicializadores, que admiten la compilación del código generado. Sin embargo, algunas de las deficiencias de C han impulsado el desarrollo de otros lenguajes basados ​​en C diseñados específicamente para su uso como lenguajes intermedios, como C-- . Además, los principales compiladores contemporáneos, GCC y LLVM , cuentan con una representación intermedia que no es C, y esos compiladores admiten interfaces para muchos lenguajes, incluido C.

Algunos otros idiomas están escritos en C.

Una consecuencia de la amplia disponibilidad y eficiencia de C es que los compiladores , bibliotecas e intérpretes de otros lenguajes de programación a menudo se implementan en C. [45] Por ejemplo, las implementaciones de referencia de Python , [46] Perl , [47] Ruby , [48] y PHP [49] están escritos en C.

Una vez utilizado para el desarrollo web.

Históricamente, C se utilizaba a veces para el desarrollo web utilizando la interfaz de puerta de enlace común (CGI) como "puerta de enlace" para la información entre la aplicación web, el servidor y el navegador. [50] Es posible que se haya elegido C en lugar de los lenguajes interpretados debido a su velocidad, estabilidad y disponibilidad casi universal. [51] Ya no es una práctica común que el desarrollo web se realice en C, [52] y existen muchas otras herramientas de desarrollo web .

Aplicaciones de usuario final

C también se ha utilizado ampliamente para implementar aplicaciones de usuario final . [53] Sin embargo, estas aplicaciones también pueden escribirse en lenguajes más nuevos y de nivel superior.

Limitaciones

el poder del lenguaje ensamblador y la conveniencia de... lenguaje ensamblador

—Dennis  Ritchie [54]

Si bien C ha sido popular, influyente y de gran éxito, tiene desventajas, entre ellas:

Para algunos propósitos, se han adoptado estilos restringidos de C, por ejemplo, MISRA C o CERT C , en un intento de reducir la posibilidad de errores. Las bases de datos como CWE intentan contar las formas en que C, etc. tiene vulnerabilidades, junto con recomendaciones para mitigación.

Existen herramientas que pueden mitigar algunos de los inconvenientes. Los compiladores de C contemporáneos incluyen comprobaciones que pueden generar advertencias para ayudar a identificar muchos errores potenciales.

Algunos de estos inconvenientes han impulsado la construcción de otros lenguajes. [ cita necesaria ]

Idiomas relacionados

El gráfico del índice TIOBE , que muestra una comparación de la popularidad de varios lenguajes de programación [60]

C ha influido directa e indirectamente en muchos lenguajes posteriores como C++ y Java . [61] La influencia más generalizada ha sido sintáctica; Todos los lenguajes mencionados combinan la sintaxis de declaraciones y (más o menos reconocibles) expresiones de C con sistemas de tipos, modelos de datos o estructuras de programas a gran escala que difieren de las de C, a veces radicalmente.

Existen varios intérpretes C o casi C, incluidos Ch y CINT , que también se pueden utilizar para secuencias de comandos.

Cuando los lenguajes de programación orientados a objetos se hicieron populares, C++ y Objective-C eran dos extensiones diferentes de C que proporcionaban capacidades orientadas a objetos. Ambos lenguajes se implementaron originalmente como compiladores de fuente a fuente ; El código fuente se tradujo a C y luego se compiló con un compilador de C. [62]

El lenguaje de programación C++ (originalmente llamado "C con clases ") fue ideado por Bjarne Stroustrup como un enfoque para proporcionar funcionalidad orientada a objetos con una sintaxis similar a la de C. [63] C++ agrega mayor fuerza de escritura, alcance y otras herramientas útiles en la programación orientada a objetos, y permite la programación genérica a través de plantillas. Casi un superconjunto de C, C++ ahora [ ¿cuándo? ] admite la mayor parte de C, con algunas excepciones .

Objective-C era originalmente una capa muy "delgada" encima de C, y sigue siendo un superconjunto estricto de C que permite la programación orientada a objetos utilizando un paradigma de tipificación híbrido dinámico/estático. Objective-C deriva su sintaxis tanto de C como de Smalltalk : la sintaxis que implica preprocesamiento, expresiones, declaraciones de funciones y llamadas a funciones se hereda de C, mientras que la sintaxis para las funciones orientadas a objetos se tomó originalmente de Smalltalk.

Además de C++ y Objective-C , Ch , Cilk y Unified Parallel C son casi superconjuntos de C.

Ver también

Notas

  1. ^ El código de ejemplo original se compilará en la mayoría de los compiladores modernos que no están en modo de cumplimiento estándar estricto, pero no cumple completamente con los requisitos de C89 o C99. De hecho, C99 requiere que se produzca un mensaje de diagnóstico.
  2. ^ La mainfunción en realidad tiene dos argumentos int argcy char *argv[], respectivamente, que pueden usarse para manejar argumentos de línea de comandos . El estándar ISO C (sección 5.1.2.2.1) requiere que mainse admitan ambas formas, lo cual es un tratamiento especial que no se otorga a ninguna otra función.
  3. ^ El código de print_array(no se muestra) difiere ligeramente, [ ¿por qué? ] también.

Referencias

  1. ^ ab Prinz, Peter; Crawford, Tony (16 de diciembre de 2005). C en pocas palabras. O'Reilly Media, Inc. pág. 3.ISBN​ 9780596550714.
  2. ^ Ritchie (1993): "Thompson había hecho un breve intento de producir un sistema codificado en una versión temprana de C, antes de las estructuras, en 1972, pero abandonó el esfuerzo".
  3. ^ "C - Estado e hitos del proyecto". ISO/CEI JTC1/SC22/WG14 . Estándares abiertos. 5 de abril de 2023 . Consultado el 9 de agosto de 2023 .
  4. ^ Ritchie (1993): "El esquema de composición tipográfica adoptado por C tiene una deuda considerable con Algol 68, aunque tal vez no surgió en una forma que los seguidores de Algol aprobarían".
  5. ^ ab "Verilog HDL (y C)" (PDF) . La Escuela de Investigación en Ciencias de la Computación de la Universidad Nacional de Australia. 3 de junio de 2010. Archivado desde el original (PDF) el 6 de noviembre de 2013 . Consultado el 19 de agosto de 2013 . Década de 1980: Verilog se introduce por primera vez; Verilog inspirado en el lenguaje de programación C
  6. ^ "El nombre se basa y se pronuncia como la letra C del alfabeto inglés". el sonido del lenguaje de programación c . Diccionario inglés chino. Archivado desde el original el 17 de noviembre de 2022 . Consultado el 17 de noviembre de 2022 .
  7. ^ "El lenguaje C cae al índice de popularidad más bajo". Desarrollador.com . 9 de agosto de 2016. Archivado desde el original el 22 de agosto de 2022 . Consultado el 1 de agosto de 2022 .
  8. ^ abcdef Ritchie (1993)
  9. ^ "Popularidad del lenguaje de programación". 2009. Archivado desde el original el 16 de enero de 2009 . Consultado el 16 de enero de 2009 .
  10. ^ "Índice de la comunidad de programación TIOBE". 2009. Archivado desde el original el 4 de mayo de 2009 . Consultado el 6 de mayo de 2009 .
  11. ^ Ward, Terry A. (agosto de 1983). "Bibliografía C/A comentada del lenguaje C". Byte . pag. 268 . Consultado el 31 de enero de 2015 .
  12. ^ "Índice TIOBE de octubre de 2021". Archivado desde el original el 25 de febrero de 2018 . Consultado el 7 de octubre de 2021 .
  13. ^ Ritchie, Dennis. "BCPL a B a C". Archivado desde el original el 12 de diciembre de 2019 . Consultado el 10 de septiembre de 2019 .
  14. ^ abcde Jensen, Richard (9 de diciembre de 2020). ""Una cosa muy estúpida ": los orígenes de C". Ars Técnica . Archivado desde el original el 28 de marzo de 2022 . Consultado el 28 de marzo de 2022 .
  15. ^ ab Johnson, Carolina del Sur ; Ritchie, DM (1978). "Portabilidad de Programas C y el Sistema UNIX". Tecnología del sistema de campana. J.57 (6): 2021-2048. CiteSeerX 10.1.1.138.35 . doi :10.1002/j.1538-7305.1978.tb02141.x. S2CID  17510065. (Nota: el PDF es un escaneo OCR del original y contiene una representación de "IBM 370" como "IBM 310".)
  16. ^ McIlroy, Doctor en Medicina (1987). Un lector de Research Unix: extractos comentados del Manual del programador, 1971-1986 (PDF) (Informe técnico). CSTR. Laboratorios Bell. pag. 10. 139. Archivado (PDF) desde el original el 11 de noviembre de 2017 . Consultado el 1 de febrero de 2015 .
  17. ^ Kernighan, Brian W .; Ritchie, Dennis M. (febrero de 1978). El lenguaje de programación C (1ª ed.). Englewood Cliffs, Nueva Jersey : Prentice Hall . ISBN 978-0-13-110163-0.
  18. ^ "Páginas del manual C". Manual de información diversa de FreeBSD (FreeBSD 13.0 ed.). 30 de mayo de 2011. Archivado desde el original el 21 de enero de 2021 . Consultado el 15 de enero de 2021 .[1] Archivado el 21 de enero de 2021 en Wayback Machine.
  19. ^ Kernighan, Brian W .; Ritchie, Dennis M. (marzo de 1988). El lenguaje de programación C (2ª ed.). Englewood Cliffs, Nueva Jersey : Prentice Hall . ISBN 978-0-13-110362-7.
  20. ^ Stroustrup, Bjarne (2002). Rivalidad entre hermanos: C y C++ (PDF) (Reporte). Laboratorios AT&T. Archivado (PDF) desde el original el 24 de agosto de 2014 . Consultado el 14 de abril de 2014 .
  21. ^ C Integridad. Organización Internacional de Normalización. 30 de marzo de 1995. Archivado desde el original el 25 de julio de 2018 . Consultado el 24 de julio de 2018 .
  22. ^ "JTC1/SC22/WG14-C". Página de inicio . ISO/CEI. Archivado desde el original el 12 de febrero de 2018 . Consultado el 2 de junio de 2011 .
  23. ^ Andrew Binstock (12 de octubre de 2011). "Entrevista con Herb Sutter". Doctor Dobbs . Archivado desde el original el 2 de agosto de 2013 . Consultado el 7 de septiembre de 2013 .
  24. ^ "WG14-N3132: Calendario C23 revisado" (PDF) . open-std.org . 4 de junio de 2023. Archivado (PDF) desde el original el 9 de junio de 2023.
  25. ^ "WG14-N3220: Borrador de trabajo, C2y" (PDF) . open-std.org . 21 de febrero de 2024. Archivado (PDF) desde el original el 26 de febrero de 2024.
  26. ^ "TR 18037: C integrado" (PDF) . ISO/IEC. Archivado (PDF) desde el original el 25 de febrero de 2021 . Consultado el 26 de julio de 2011 .
  27. ^ Harbison, Samuel P.; Steele, Guy L. (2002). C: Un manual de referencia (5ª ed.). Englewood Cliffs, Nueva Jersey : Prentice Hall . ISBN 978-0-13-089592-9.Contiene una gramática BNF para C.
  28. ^ Kernighan y Ritchie (1988), pág. 192.
  29. ^ Kernighan y Ritchie (1978), pág. 3.
  30. ^ "Borrador del Comité ISO/IEC 9899:201x (ISO C11)" (PDF) . Archivado (PDF) desde el original el 22 de diciembre de 2017 . Consultado el 16 de septiembre de 2011 .
  31. ^ Kernighan y Ritchie (1988), págs.192, 259.
  32. ^ "Diez errores comunes de programación en C++". Cs.ucr.edu. Archivado desde el original el 21 de octubre de 2008 . Consultado el 26 de junio de 2009 .
  33. ^ Schultz, Thomas (2004). C y el 8051 (3ª ed.). Otsego, MI: PageFree Publishing Inc. p. 20.ISBN 978-1-58961-237-2. Consultado el 10 de febrero de 2012 .
  34. ^ Kernighan y Ritchie (1978), pág. 6.
  35. ^ abcdefg Klemens, Ben (2013). Siglo XXI C. Medios O'Reilly . ISBN 978-1-4493-2714-9.
  36. ^ Feuer, Alan R.; Gehani, Narain H. (marzo de 1982). "Comparación de los lenguajes de programación C y Pascal". Encuestas de Computación ACM . 14 (1): 73–92. doi :10.1145/356869.356872. S2CID  3136859.
  37. ^ Kernighan y Ritchie (1988), pág. 122.
  38. ^ Por ejemplo, gcc proporciona _FORTIFY_SOURCE. "Funciones de seguridad: comprobaciones del búfer de tiempo de compilación (FORTIFY_SOURCE)". fedoraproject.org. Archivado desde el original el 7 de enero de 2007 . Consultado el 5 de agosto de 2012 .
  39. ^ เอี่ยมสิริวงศ์, โอภาศ (2016). Programación con C. Bangkok, Tailandia: SE-EDUCATION PUBLIC COMPANY LIMITED. págs. 225-230. ISBN 978-616-08-2740-4.
  40. ^ Raymond, Eric S. (11 de octubre de 1996). El diccionario del nuevo hacker (3ª ed.). Prensa del MIT. pag. 432.ISBN 978-0-262-68092-9. Consultado el 5 de agosto de 2012 .
  41. ^ "Página de manual de pelusa (sección 1 de freebsd)". unix.com . 24 de mayo de 2001 . Consultado el 15 de julio de 2014 .
  42. ^ "CS107 Valgrind Memcheck". web.stanford.edu . Consultado el 23 de junio de 2023 .
  43. ^ Hastings, caña; Joyce, Bob. "Purify: Detección rápida de pérdidas de memoria y errores de acceso" (PDF) . Puro Software Inc .: 9.
  44. ^ Dale, Nell B.; Weems, chip (2014). Programación y resolución de problemas con C++ (6ª ed.). Burlington, Massachusetts: Jones & Bartlett Learning. ISBN 978-1449694289. OCLC  894992484.
  45. ^ "C - la madre de todos los idiomas". Academia de TIC en IITK . 13 de noviembre de 2018. Archivado desde el original el 31 de mayo de 2021 . Consultado el 11 de octubre de 2022 .
  46. ^ "1. Ampliar Python con C o C++". Documentación de Python 3.10.7 . Archivado desde el original el 5 de noviembre de 2012 . Consultado el 11 de octubre de 2022 .
  47. ^ Conrad, Michael (22 de enero de 2018). "Una descripción general del motor Perl 5". Opensource.com . Archivado desde el original el 26 de mayo de 2022 . Consultado el 11 de octubre de 2022 .
  48. ^ "A Ruby desde C y C++". Lenguaje de programación Ruby . Archivado desde el original el 12 de agosto de 2013 . Consultado el 11 de octubre de 2022 .
  49. ^ Para, Michael (3 de agosto de 2022). "¿Qué es PHP? Cómo escribir su primer programa PHP". Campamento de código gratuito . Archivado desde el original el 4 de agosto de 2022 . Consultado el 11 de octubre de 2022 .
  50. ^ Libro de consulta del Dr. Dobb . Estados Unidos: Miller Freeman, Inc. Noviembre-diciembre de 1995.
  51. ^ "Uso de C para programación CGI". linuxjournal.com. 1 de marzo de 2005. Archivado desde el original el 13 de febrero de 2010 . Consultado el 4 de enero de 2010 .
  52. ^ Perkins, Luc (17 de septiembre de 2013). "Desarrollo web en C: ¿loco? ¿O loco como un zorro?". Medio . Archivado desde el original el 4 de octubre de 2014 . Consultado el 8 de abril de 2022 .
  53. ^ Muñoz, Daniel. "Después de todos estos años, el mundo todavía funciona con la programación C". Blog de ingeniería de Toptal . Consultado el 17 de noviembre de 2023 .
  54. ^ Metz, Cade. "Dennis Ritchie: Los hombros sobre los que se apoyó Steve Jobs". Cableado . Archivado desde el original el 12 de abril de 2022 . Consultado el 19 de abril de 2022 .
  55. ^ corob-msft (31 de marzo de 2022). "Directivas Pragma y las palabras clave __pragma y _Pragma". Microsoft aprende . Archivado desde el original el 24 de septiembre de 2022 . Consultado el 24 de septiembre de 2022 .
  56. ^ "Pragmas (el preprocesador C)". GCC, la colección de compiladores GNU . Archivado desde el original el 17 de junio de 2002 . Consultado el 24 de septiembre de 2022 .
  57. ^ "Pragmas". Guía y referencia para desarrolladores de Intel C++ Compiler Classic . Intel. Archivado desde el original el 10 de abril de 2022 . Consultado el 10 de abril de 2022 .
  58. ^ "Elogio del preprocesador C". apenwarr . 13 de agosto de 2007 . Consultado el 9 de julio de 2023 .
  59. ^ Roberts, Eric S. (21 de marzo de 1989). "Implementación de excepciones en C" (PDF) . Centro de Investigación de Sistemas DEC . SRC-RR-40. Archivado (PDF) desde el original el 15 de enero de 2017 . Consultado el 4 de enero de 2022 .
  60. ^ McMillan, Robert (1 de agosto de 2013). "¿Java está perdiendo su encanto?". Cableado . Archivado desde el original el 15 de febrero de 2017 . Consultado el 5 de marzo de 2017 .
  61. ^ O'Regan, Gerard (24 de septiembre de 2015). Pilares de la informática: un compendio de empresas tecnológicas seleccionadas y fundamentales . Saltador. ISBN 978-3319214641. OCLC  922324121.
  62. ^ Rauchwerger, Lawrence (2004). Lenguajes y compiladores para computación paralela: 16º taller internacional, LCPC 2003, College Station, TX, EE. UU., 2 al 4 de octubre de 2003: artículos revisados . Saltador. ISBN 978-3540246442. OCLC  57965544.
  63. ^ Stroustrup, Bjarne (1993). "Una historia de C++: 1979-1991" (PDF) . Archivado (PDF) desde el original el 2 de febrero de 2019 . Consultado el 9 de junio de 2011 .

Fuentes

Otras lecturas

enlaces externos