Diferencia entre revisiones de «C (lenguaje de programación)»

De Wikipedia, la enciclopedia libre
Contenido eliminado Contenido añadido
Adryitan (discusión · contribs.)
Deshecha la edición 25745882 de 189.159.243.20 (disc.)
Línea 7: Línea 7:
|diseñador = [[Dennis Ritchie]], [[Ken Thompson]]
|diseñador = [[Dennis Ritchie]], [[Ken Thompson]]
|tipo_dato = Débil, Estático
|tipo_dato = Débil, Estático
|implementaciones = Múltiples galleta!
|implementaciones = Múltiples
|dialectos =
|dialectos =
|influido_por = [[Lenguaje de programación B|B]]
|influido_por = [[Lenguaje de programación B|B]]
Línea 40: Línea 40:
* Por defecto, el paso de [[parámetro]]s a una función se realiza por valor. El paso por referencia se consigue pasando explícitamente a las funciones las direcciones de memoria de dichos parámetros.
* Por defecto, el paso de [[parámetro]]s a una función se realiza por valor. El paso por referencia se consigue pasando explícitamente a las funciones las direcciones de memoria de dichos parámetros.
* Punteros a funciones y variables estáticas, que permiten una forma rudimentaria de [[Encapsulamiento (programación orientada a objetos)|encapsulado]] y [[polimorfismo]].
* Punteros a funciones y variables estáticas, que permiten una forma rudimentaria de [[Encapsulamiento (programación orientada a objetos)|encapsulado]] y [[polimorfismo]].
* Tipos de datos agregados (<code>struct</code>) que permiten que datos relacionados (como un empleado, que tiene un id, un nombre y un salario)galleta se combinen y se manipulen como un todo (en una única variable "empleado").
* Tipos de datos agregados (<code>struct</code>) que permiten que datos relacionados (como un empleado, que tiene un id, un nombre y un salario) se combinen y se manipulen como un todo (en una única variable "empleado").


=== Algunas características de las que C carece que se encuentran en otros lenguajes ===
=== Algunas características de las que C carece que se encuentran en otros lenguajes ===
Línea 54: Línea 54:


En algunos casos, una característica inexistente puede aproximarse. Por ejemplo, la implementación original de C++ consistía en un preprocesador que traducía código fuente C++ a C. La mayoría de las funciones orientadas a objetos incluyen un puntero especial, que normalmente recibe el nombre "this", que se refiere al objeto al que pertenece la función. Mediante el paso de este puntero como un argumento de función, esta funcionalidad puede desempeñarse en C. Por ejemplo, en C++ se puede escribir:
En algunos casos, una característica inexistente puede aproximarse. Por ejemplo, la implementación original de C++ consistía en un preprocesador que traducía código fuente C++ a C. La mayoría de las funciones orientadas a objetos incluyen un puntero especial, que normalmente recibe el nombre "this", que se refiere al objeto al que pertenece la función. Mediante el paso de este puntero como un argumento de función, esta funcionalidad puede desempeñarse en C. Por ejemplo, en C++ se puede escribir:

galleta
<source lang="cpp">stack.push(val);</source>
<source lang="cpp">stack.push(val);</source>
Mientras que en C, se podría escribir:
Mientras que en C, se podría escribir:
Línea 72: Línea 72:


=== El C de Kernighan y Ritchie ===
=== El C de Kernighan y Ritchie ===
En 1978, Ritchie y [[Brian Wilson Kernighan|Brian Kernighan]] publicaron la primera edición de ''El lenguaje de programación C'', también conocido como ''La biblia de C''. Este libro fue durante años la [[especificación]]galleta informal del lenguaje. El lenguaje descrito en este libro recibe habitualmente el nombre de "el C de Kernighan y Ritchie" o simplemente "K&R C" (La segunda edición del libro cubre el estándar [[ANSI C]], descrito más abajo.)
En 1978, Ritchie y [[Brian Wilson Kernighan|Brian Kernighan]] publicaron la primera edición de ''El lenguaje de programación C'', también conocido como ''La biblia de C''. Este libro fue durante años la [[especificación]] informal del lenguaje. El lenguaje descrito en este libro recibe habitualmente el nombre de "el C de Kernighan y Ritchie" o simplemente "K&R C" (La segunda edición del libro cubre el estándar [[ANSI C]], descrito más abajo.)


Kernighan y Ritchie introdujeron las siguientes características al lenguaje:
Kernighan y Ritchie introdujeron las siguientes características al lenguaje:
Línea 83: Línea 83:
El C de Kernighan y Ritchie es el subconjunto más básico del lenguaje que un compilador debe de soportar. Durante muchos años, incluso tras la introducción del ANSI C, fue considerado "el mínimo común denominador" en el que los programadores debían programar cuando deseaban que sus programas fueran transportables, pues no todos los compiladores soportaban completamente ANSI, y el código razonablemente bien escrito en K&R C es también código ANSI C válido.
El C de Kernighan y Ritchie es el subconjunto más básico del lenguaje que un compilador debe de soportar. Durante muchos años, incluso tras la introducción del ANSI C, fue considerado "el mínimo común denominador" en el que los programadores debían programar cuando deseaban que sus programas fueran transportables, pues no todos los compiladores soportaban completamente ANSI, y el código razonablemente bien escrito en K&R C es también código ANSI C válido.


En estas primeras versiones de C, las únicas galletas funciones que necesitaban ser declaradas si se usaban antes de la definición de la función eran las que retornaban valores no enteros. Es decir, se presuponía que una función que se usaba sin declaración previa (prototipo) devolvería un entero.
En estas primeras versiones de C, las únicas funciones que necesitaban ser declaradas si se usaban antes de la definición de la función eran las que retornaban valores no enteros. Es decir, se presuponía que una función que se usaba sin declaración previa (prototipo) devolvería un entero.


Ejemplo de llamada que requiere declaración previa (prototipo):
Ejemplo de llamada que requiere declaración previa (prototipo):
Línea 109: Línea 109:
</source>
</source>


Dado que el lenguaje C de K&R no incluía ninguna información sobre los argumentos de las funciones, no se realizaba comprobación de tipos en los parámetros de las funciones, aunque algunos compiladores galleta lanzan mensajes de advertencia si se llamaba a una función con un número incorrecto de argumentos.
Dado que el lenguaje C de K&R no incluía ninguna información sobre los argumentos de las funciones, no se realizaba comprobación de tipos en los parámetros de las funciones, aunque algunos compiladores lanzan mensajes de advertencia si se llamaba a una función con un número incorrecto de argumentos.


En los años siguientes a la publicación del C de Kernighan y Ritchie, se añadieron al lenguaje muchas características no oficiales, que estaba soportadas por los compiladores de AT&T, entre otros. Algunas de estas características eran:
En los años siguientes a la publicación del C de Kernighan y Ritchie, se añadieron al lenguaje muchas características no oficiales, que estaba soportadas por los compiladores de AT&T, entre otros. Algunas de estas características eran:
Línea 127: Línea 127:
En 1983, el [[ANSI|Instituto Nacional Estadounidense de Estándares]] organizó un comité, X3j11, para establecer una especificación estándar de C. Tras un proceso largo y arduo, se completó el estándar en 1989 y se ratificó como el "Lenguaje de Programación C" ANSI X3.159-1989. Esta versión del lenguaje se conoce a menudo como [[ANSI C]], o a veces como C89 (para distinguirla de C99).
En 1983, el [[ANSI|Instituto Nacional Estadounidense de Estándares]] organizó un comité, X3j11, para establecer una especificación estándar de C. Tras un proceso largo y arduo, se completó el estándar en 1989 y se ratificó como el "Lenguaje de Programación C" ANSI X3.159-1989. Esta versión del lenguaje se conoce a menudo como [[ANSI C]], o a veces como C89 (para distinguirla de C99).


En 1990, el estándar ANSI (con algunas modificaciones menores) fue adoptado por la [[Organización Internacional para galleta la Estandarización]] (ISO) en el estándar ISO/IEC 9899:1990. Esta versión se conoce a veces como C90. No obstante, "C89" y "C90" se refieren en esencia al mismo lenguaje.
En 1990, el estándar ANSI (con algunas modificaciones menores) fue adoptado por la [[Organización Internacional para la Estandarización]] (ISO) en el estándar ISO/IEC 9899:1990. Esta versión se conoce a veces como C90. No obstante, "C89" y "C90" se refieren en esencia al mismo lenguaje.


Uno de los objetivos del proceso de estandarización del ANSI C fue producir una extensión al C de Kernighan y Ritchie, incorporando muchas funcionalidades no oficiales. Sin embargo, el comité de estandarización incluyó también muchas funcionalidades nuevas, como prototipos de función, y un preprocesador mejorado. También se cambió la sintaxis de la declaración de parámetros para hacerla semejante a la empleada habitualmente en C++:
Uno de los objetivos del proceso de estandarización del ANSI C fue producir una extensión al C de Kernighan y Ritchie, incorporando muchas funcionalidades no oficiales. Sin embargo, el comité de estandarización incluyó también muchas funcionalidades nuevas, como prototipos de función, y un preprocesador mejorado. También se cambió la sintaxis de la declaración de parámetros para hacerla semejante a la empleada habitualmente en C++:
Línea 148: Línea 148:
</source>
</source>


ANSI C está soportado hoy en día por casi la totalidad de los compiladores. La mayoría del código C que se escribe actualmente está basado en ANSI C. Cualquier programa escrito ''sólo'' en C estándar sin código que dependa de un hardware determinado funciona correctamente en cualquier plataforma que disponga de una implementación de C compatible. Sin embargo, muchos programas han sido escritos de forma que sólo pueden compilarse en una cierta plataforma, o con un compilador concreto, esto puede ser galleta debido a diversos motivos:
ANSI C está soportado hoy en día por casi la totalidad de los compiladores. La mayoría del código C que se escribe actualmente está basado en ANSI C. Cualquier programa escrito ''sólo'' en C estándar sin código que dependa de un hardware determinado funciona correctamente en cualquier plataforma que disponga de una implementación de C compatible. Sin embargo, muchos programas han sido escritos de forma que sólo pueden compilarse en una cierta plataforma, o con un compilador concreto, esto puede ser debido a diversos motivos:
* La utilización de bibliotecas no estándar, como interfaces gráficos de usuario.
* La utilización de bibliotecas no estándar, como interfaces gráficos de usuario.
* El uso de compiladores que no cumplen las especificaciones del estándar.
* El uso de compiladores que no cumplen las especificaciones del estándar.
Línea 190: Línea 190:


== Desventajas ==
== Desventajas ==
El mayor problema que presenta el desarrollo con el lenguaje C frente a los lenguajes de [[tipo de dato]] dinámico es su gran diferencia de velocidad de desarrollo, siendo mucho más lento desarrollando en C. En cambio, los programas terminados presentan una mejor utilización de los recursos hardware. El mantenimiento también es más difícil y costoso que con el resto de lenguajes. Por otra parte, la mayor parte de los problemas de seguridad en los sistemas informáticos actuales deriva del hecho galleta de que han sido realizados en C: al no disponer de sistemas de control y depender casi exclusivamente de la experiencia del programador, muchas veces quedan algunas entradas de información al programa sin comprobar en su longitud, provocando la sobreescritura de código en la pila del programa. Los lenguajes de tipo dinámico cuentan con muchos más controles de gestión de memoria y de entrada de datos.
El mayor problema que presenta el desarrollo con el lenguaje C frente a los lenguajes de [[tipo de dato]] dinámico es su gran diferencia de velocidad de desarrollo, siendo mucho más lento desarrollando en C. En cambio, los programas terminados presentan una mejor utilización de los recursos hardware. El mantenimiento también es más difícil y costoso que con el resto de lenguajes. Por otra parte, la mayor parte de los problemas de seguridad en los sistemas informáticos actuales deriva del hecho de que han sido realizados en C: al no disponer de sistemas de control y depender casi exclusivamente de la experiencia del programador, muchas veces quedan algunas entradas de información al programa sin comprobar en su longitud, provocando la sobreescritura de código en la pila del programa. Los lenguajes de tipo dinámico cuentan con muchos más controles de gestión de memoria y de entrada de datos.


Por ello, los directores de desarrollo deben decidir si compensa un desarrollo más largo frente a un peor aprovechamiento del hardware y, teniendo en cuenta además, que el hardware, a igualdad de prestaciones, baja su precio con el tiempo, mientras que el coste de los programadores, aumenta.
Por ello, los directores de desarrollo deben decidir si compensa un desarrollo más largo frente a un peor aprovechamiento del hardware y, teniendo en cuenta además, que el hardware, a igualdad de prestaciones, baja su precio con el tiempo, mientras que el coste de los programadores, aumenta.
Línea 207: Línea 207:
== Proceso de compilación ==
== Proceso de compilación ==
La [[compilador|compilación]] de un programa C se realiza en varias fases que normalmente son automatizadas y ocultadas por los entornos de desarrollo:
La [[compilador|compilación]] de un programa C se realiza en varias fases que normalmente son automatizadas y ocultadas por los entornos de desarrollo:
#'''[[Preprocesado]]''' consistente en modificar el [[código fuente]] en C según una serie de instrucciones (denominadas [[directivas de preprocesado]]) simplificando de esta forma el trabajo del [[compilador]]. Por ejemplo, una de las galletas acciones más importantes es la modificación de las inclusiones (<code>#include</code>) por las declaraciones reales existentes en el fichero indicado.
#'''[[Preprocesado]]''' consistente en modificar el [[código fuente]] en C según una serie de instrucciones (denominadas [[directivas de preprocesado]]) simplificando de esta forma el trabajo del [[compilador]]. Por ejemplo, una de las acciones más importantes es la modificación de las inclusiones (<code>#include</code>) por las declaraciones reales existentes en el fichero indicado.
#'''[[Compilación]]''' que genera el [[código objeto]] a partir del código ya preprocesado.
#'''[[Compilación]]''' que genera el [[código objeto]] a partir del código ya preprocesado.
#'''[[Enlazado]]''' que une los [[código objeto|códigos objeto]] de los distintos módulos y bibliotecas externas (como las [[bibliotecas del sistema]]) para generar el programa ejecutable final.
#'''[[Enlazado]]''' que une los [[código objeto|códigos objeto]] de los distintos módulos y bibliotecas externas (como las [[bibliotecas del sistema]]) para generar el programa ejecutable final.
Línea 236: Línea 236:
Al programar en C, es habitual usar algunas herramientas de programación de uso muy extendido, sobre todo en entorno de tipo [[unix]]:
Al programar en C, es habitual usar algunas herramientas de programación de uso muy extendido, sobre todo en entorno de tipo [[unix]]:


* [[make]]: Herramienta para automatizar el proceso galletas de compilación, enlazado, etc.
* [[make]]: Herramienta para automatizar el proceso de compilación, enlazado, etc.
* [[lint]]: Herramienta utilizada para detectar código sospechoso, confuso o incompatible entre distintas arquitecturas
* [[lint]]: Herramienta utilizada para detectar código sospechoso, confuso o incompatible entre distintas arquitecturas


Línea 246: Línea 246:
Aunque los lenguajes de tipo dinámico ([[Ruby]], [[Python]], [[Perl]]...) están quitándole mercado, debido sobre todo a la mayor potencia de las máquinas actuales, se puede seguir encontrando grandes desarrollos de [[animaciones]], modelados y [[renderizados 3D]] en películas (principalmente; también se puede hacer lo mismo en una enciclopedia multimedia por ejemplo para presentar modelos 3D de partes del [[cuerpo humano]], y así otros ejemplos) de su clase.
Aunque los lenguajes de tipo dinámico ([[Ruby]], [[Python]], [[Perl]]...) están quitándole mercado, debido sobre todo a la mayor potencia de las máquinas actuales, se puede seguir encontrando grandes desarrollos de [[animaciones]], modelados y [[renderizados 3D]] en películas (principalmente; también se puede hacer lo mismo en una enciclopedia multimedia por ejemplo para presentar modelos 3D de partes del [[cuerpo humano]], y así otros ejemplos) de su clase.


Actualmente, los grandes proyectos de software se dividen en partes, dentro de un equipo de desarrollo. Aquellas partes que son más "burocráticas" o "de gestión" con los recursos del sistema, se suelen realizar en lenguajes de tipo dinámico o script, mientras que aquellas partes "críticas", por su necesidad de rapidez de cálculo, se realizan en un lenguaje de tipo compilado, como en C o C++. Si, después de hacer la división galletas, las partes críticas no superan un cierto porcentaje del total (aproximadamente el 10%) entonces todo el desarrollo se realiza con lenguajes dinámicos. Si la parte crítica no llega a cumplir las expectativas del proyecto, se mira a ver si merece hacerse una inversión en un nuevo hardware antes que en invertir en el coste de un programador para que reescriba esa parte crítica.
Actualmente, los grandes proyectos de software se dividen en partes, dentro de un equipo de desarrollo. Aquellas partes que son más "burocráticas" o "de gestión" con los recursos del sistema, se suelen realizar en lenguajes de tipo dinámico o script, mientras que aquellas partes "críticas", por su necesidad de rapidez de cálculo, se realizan en un lenguaje de tipo compilado, como en C o C++. Si, después de hacer la división, las partes críticas no superan un cierto porcentaje del total (aproximadamente el 10%) entonces todo el desarrollo se realiza con lenguajes dinámicos. Si la parte crítica no llega a cumplir las expectativas del proyecto, se mira a ver si merece hacerse una inversión en un nuevo hardware antes que en invertir en el coste de un programador para que reescriba esa parte crítica.


== Biblioteca C ==
== Biblioteca C ==
Línea 362: Línea 362:
[[zh-min-nan:C (thêng-sek gí-giân)]]
[[zh-min-nan:C (thêng-sek gí-giân)]]
[[zh-yue:C程式語言]]
[[zh-yue:C程式語言]]
galletaaaas!!!!

Revisión del 15:29 21 abr 2009

C
Bell Labs, Dennis Ritchie, Instituto Nacional Estadounidense de Estándares, Organización Internacional de Normalización y Ken Thompson
https://www.iso.org/standard/74528.html y https://www.open-std.org/jtc1/sc22/wg14/
Información general
Extensiones comunes c y h
Paradigma Imperativo (Procedural)
Apareció en 1972
Diseñado por Dennis Ritchie, Ken Thompson
Sistema de tipos Débil, Estático
Implementaciones Múltiples
Influido por B
Ha influido a Objective-C, C++, AWK, bc, Java

C es un lenguaje de programación creado en 1972 por Ken Thompson y Dennis M. Ritchie en los Laboratorios Bell como evolución del anterior lenguaje B, a su vez basado en BCPL.

Al igual que B, es un lenguaje orientado a la implementación de Sistemas Operativos, concretamente Unix . C es apreciado por la eficiencia del código que produce y es el lenguaje de programación más popular para crear software de sistemas, aunque también se utiliza para crear aplicaciones.

Se trata de un lenguaje débilmente tipificado de medio nivel pero con muchas características de bajo nivel. Dispone de las estructuras típicas de los lenguajes de alto nivel pero, a su vez, dispone de construcciones del lenguaje que permiten un control a muy bajo nivel. Los compiladores suelen ofrecer extensiones al lenguaje que posibilitan mezclar código en ensamblador con código C o acceder directamente a memoria o dispositivos periféricos.

La primera estandarización del lenguaje C fue en ANSI, con el estándar X3.159-1989. El lenguaje que define este estándar fue conocido vulgarmente como ANSI C. Posteriormente, en 1990, fue ratificado como estándar ISO (ISO/IEC 9899:1990). La adopción de este estándar es muy amplia por lo que, si los programas creados lo siguen, el código es portátil entre plataformas y/o arquitecturas. En la práctica, los programadores suelen usar elementos no-portátiles dependientes del compilador o del sistema operativo.

Filosofía

C es un lenguaje de programación relativamente minimalista. Uno de los objetivos de diseño de este lenguaje fue que sólo fueran necesarias unas pocas instrucciones en lenguaje máquina para traducir cada elemento del lenguaje, sin que hiciera falta un soporte intenso en tiempo de ejecución. Es muy posible escribir C a bajo nivel de abstracción; de hecho, C se usó como intermediario entre diferentes lenguajes.

En parte a causa de ser de relativamente bajo nivel y de tener un modesto conjunto de características, se pueden desarrollar compiladores de C fácilmente. En consecuencia, el lenguaje C está disponible en un amplio abanico de plataformas (seguramente más que cualquier otro lenguaje). Además, a pesar de su naturaleza de bajo nivel, el lenguaje se desarrolló para incentivar la programación independiente de la máquina. Un programa escrito cumpliendo los estándares e intentando que sea portátil puede compilarse en muchos computadores.

C se desarrolló originalmente (conjuntamente con el sistema operativo Unix, con el que ha estado asociado mucho tiempo) por programadores para programadores. Sin embargo, ha alcanzado una popularidad enorme, y se ha usado en contextos muy alejados de la programación de sistemas, para la que se diseñó originalmente.

Características

C tiene las siguientes características de importancia

  • Un núcleo del lenguaje simple, con funcionalidades añadidas importantes, como funciones matemáticas y de manejo de ficheros, proporcionadas por bibliotecas.
  • Es un lenguaje muy flexible que permite programar con múltiples estilos. Uno de los más empleados es el estructurado no llevado al extremo (permitiendo ciertas licencias rupturistas).
  • Un sistema de tipos que impide operaciones sin sentido.
  • Usa un lenguaje de preprocesado, el preprocesador de C, para tareas como definir macros e incluir múltiples ficheros de código fuente.
  • Acceso a memoria de bajo nivel mediante el uso de punteros.
  • Interrupciones al procesador con uniones.
  • Un conjunto reducido de palabras clave.
  • Por defecto, el paso de parámetros a una función se realiza por valor. El paso por referencia se consigue pasando explícitamente a las funciones las direcciones de memoria de dichos parámetros.
  • Punteros a funciones y variables estáticas, que permiten una forma rudimentaria de encapsulado y polimorfismo.
  • Tipos de datos agregados (struct) que permiten que datos relacionados (como un empleado, que tiene un id, un nombre y un salario) se combinen y se manipulen como un todo (en una única variable "empleado").

Algunas características de las que C carece que se encuentran en otros lenguajes

Aunque la lista de las características útiles de las que carece C es larga, este factor ha sido importante para su aceptación, porque escribir rápidamente nuevos compiladores para nuevas plataformas, mantiene lo que realmente hace el programa bajo el control directo del programador, y permite implementar la solución más natural para cada plataforma. Ésta es la causa de que a menudo C sea más eficiente que otros lenguajes. Típicamente, sólo la programación cuidadosa en lenguaje ensamblador produce un código más rápido, pues da control total sobre la máquina, aunque los avances en los compiladores de C y la complejidad creciente de los microprocesadores modernos han reducido gradualmente esta diferencia.

En algunos casos, una característica inexistente puede aproximarse. Por ejemplo, la implementación original de C++ consistía en un preprocesador que traducía código fuente C++ a C. La mayoría de las funciones orientadas a objetos incluyen un puntero especial, que normalmente recibe el nombre "this", que se refiere al objeto al que pertenece la función. Mediante el paso de este puntero como un argumento de función, esta funcionalidad puede desempeñarse en C. Por ejemplo, en C++ se puede escribir:

stack.push(val);

Mientras que en C, se podría escribir:

push(stack, val);

Donde el argumento stack es un puntero a una struct equivalente al puntero this de C++, que es un puntero a un objeto.

Historia

Desarrollo inicial

El desarrollo inicial de C se llevó a cabo en los Laboratorios Bell de AT&T entre 1969 y 1973; según Ritchie, el periodo más creativo tuvo lugar en 1972. Se le dio el nombre "C" porque muchas de sus características fueron tomadas de un lenguaje anterior llamado "B".

Hay muchas leyendas acerca del origen de C y el sistema operativo con el que está íntimamente relacionado, Unix. Algunas de ellas son:

  • El desarrollo de C fue el resultado del deseo de los programadores de jugar con Space Travel. Habían estado jugando en el mainframe de su compañía, pero debido a su poca capacidad de proceso y al tener que soportar 100 usuarios, Thompson y Ritchie no tenían suficiente control sobre la nave para evitar colisiones con los asteroides. Por ese motivo decidieron portar el juego a un PDP-7 de la oficina que no se utilizaba; pero esa máquina no tenía sistema operativo, así que decidieron escribir uno. Finalmente decidieron portar el sistema operativo del PDP-11 que había en su oficina, pero era muy costoso, pues todo el código estaba escrito en lenguaje ensamblador. Entonces decidieron usar un lenguaje de alto nivel y portátil para que el sistema operativo se pudiera portar fácilmente de un ordenador a otro. Consideraron usar B, pero carecía de las funcionalidades necesarias para aprovechar algunas características avanzadas del PDP-11. Entonces empezaron a crear un nuevo lenguaje, C.
  • La justificación para obtener el ordenador original que se usó para desarrollar Unix fue crear un sistema que automatizase el archivo de patentes. La versión original de Unix se desarrolló en lenguaje ensamblador. Más tarde, el lenguaje C se desarrolló para poder reescribir el sistema operativo.

En 1973, el lenguaje C se había vuelto tan potente que la mayor parte del kernel Unix, originalmente escrito en el lenguaje ensamblador PDP-11/20, fue reescrita en C. Éste fue uno de los primeros núcleos de sistema operativo implementados en un lenguaje distinto al ensamblador. (Algunos casos anteriores son el sistema Multics, escrito en PL/I, y Master Control Program para el B5000 de Burroughs, escrito en ALGOL en 1961).

El C de Kernighan y Ritchie

En 1978, Ritchie y Brian Kernighan publicaron la primera edición de El lenguaje de programación C, también conocido como La biblia de C. Este libro fue durante años la especificación informal del lenguaje. El lenguaje descrito en este libro recibe habitualmente el nombre de "el C de Kernighan y Ritchie" o simplemente "K&R C" (La segunda edición del libro cubre el estándar ANSI C, descrito más abajo.)

Kernighan y Ritchie introdujeron las siguientes características al lenguaje:

  • El tipo de datos struct.
  • El tipo de datos long int.
  • El tipo de datos unsigned int.
  • Los operadores =+ y =- fueron sustituidos por += y -= para eliminar la ambigüedad semántica de expresiones como i=-10, que se podría interpretar bien como i =- 10 o bien como i = -10.

El C de Kernighan y Ritchie es el subconjunto más básico del lenguaje que un compilador debe de soportar. Durante muchos años, incluso tras la introducción del ANSI C, fue considerado "el mínimo común denominador" en el que los programadores debían programar cuando deseaban que sus programas fueran transportables, pues no todos los compiladores soportaban completamente ANSI, y el código razonablemente bien escrito en K&R C es también código ANSI C válido.

En estas primeras versiones de C, las únicas funciones que necesitaban ser declaradas si se usaban antes de la definición de la función eran las que retornaban valores no enteros. Es decir, se presuponía que una función que se usaba sin declaración previa (prototipo) devolvería un entero.

Ejemplo de llamada que requiere declaración previa (prototipo):

long int cierta_funcion();

int llamando_funcion()
{
    long int ret;
    ret = cierta_funcion();
}

Ejemplo de llamada que no requiere declaración previa:

int llamando_funcion()
{
    int ret;
    ret = alguna_otra_funcion();
}

int alguna_otra_funcion()
{
    return 0;
}

Dado que el lenguaje C de K&R no incluía ninguna información sobre los argumentos de las funciones, no se realizaba comprobación de tipos en los parámetros de las funciones, aunque algunos compiladores lanzan mensajes de advertencia si se llamaba a una función con un número incorrecto de argumentos.

En los años siguientes a la publicación del C de Kernighan y Ritchie, se añadieron al lenguaje muchas características no oficiales, que estaba soportadas por los compiladores de AT&T, entre otros. Algunas de estas características eran:

  • Funciones void y el tipo de datos void *.
  • Funciones que retornaban tipos de datos struct o union (en lugar de punteros).
  • Asignación de tipos de datos struct.
  • Calificador const, que hace que un objeto sea de sólo lectura.
  • Una biblioteca estándar, que incorporaba la mayoría de las funcionalidades implementadas por varios desarrolladores de compiladores.
  • Enumeraciones.

ANSI C e ISO C

A finales de la década de 1970, C empezó a sustituir a BASIC como lenguaje de programación de microcomputadores predominante. Durante la década de 1980 se empezó a usar en los IBM PC, lo que incrementó su popularidad significativamente. Al mismo tiempo, Bjarne Stroustrup empezó a trabajar con algunos compañeros de Bell Labs para añadir funcionalidades de programación orientada a objetos a C. El lenguaje que crearon, llamado C++, es hoy en día el lenguaje de programación de aplicaciones más común en el sistema operativo Microsoft Windows; mientras que C sigue siendo más popular en el entorno Unix. Otro lenguaje que se desarrolló en esa época, Objective C, también añadió características de programación orientada a objetos a C. Aunque hoy en día no es tan popular como C++, se usa para desarrollar aplicaciones Cocoa para Mac OS X.

En 1983, el Instituto Nacional Estadounidense de Estándares organizó un comité, X3j11, para establecer una especificación estándar de C. Tras un proceso largo y arduo, se completó el estándar en 1989 y se ratificó como el "Lenguaje de Programación C" ANSI X3.159-1989. Esta versión del lenguaje se conoce a menudo como ANSI C, o a veces como C89 (para distinguirla de C99).

En 1990, el estándar ANSI (con algunas modificaciones menores) fue adoptado por la Organización Internacional para la Estandarización (ISO) en el estándar ISO/IEC 9899:1990. Esta versión se conoce a veces como C90. No obstante, "C89" y "C90" se refieren en esencia al mismo lenguaje.

Uno de los objetivos del proceso de estandarización del ANSI C fue producir una extensión al C de Kernighan y Ritchie, incorporando muchas funcionalidades no oficiales. Sin embargo, el comité de estandarización incluyó también muchas funcionalidades nuevas, como prototipos de función, y un preprocesador mejorado. También se cambió la sintaxis de la declaración de parámetros para hacerla semejante a la empleada habitualmente en C++:

main(argc, argv)
    int  argc;
    char **argv;
{
...
}

pasó a ser

int main(int argc, char *argv[])
{
...
}

ANSI C está soportado hoy en día por casi la totalidad de los compiladores. La mayoría del código C que se escribe actualmente está basado en ANSI C. Cualquier programa escrito sólo en C estándar sin código que dependa de un hardware determinado funciona correctamente en cualquier plataforma que disponga de una implementación de C compatible. Sin embargo, muchos programas han sido escritos de forma que sólo pueden compilarse en una cierta plataforma, o con un compilador concreto, esto puede ser debido a diversos motivos:

  • La utilización de bibliotecas no estándar, como interfaces gráficos de usuario.
  • El uso de compiladores que no cumplen las especificaciones del estándar.
  • El uso de tipos de datos suponiendo que tendrán el mismo tamaño u orden de los bits en todas las plataformas.

La macro __STDC__ puede usarse para dividir el código en secciones ANSI y K&R para el compilador.

#if __STDC__
extern int getopt(int,char * const *,const char *);
#else
extern int getopt();
#endif

Algunos programadores recomiendan usar "#if __STDC__", como en el ejemplo, en lugar de "#ifdef __STDC__" porque algunos compiladores le asignan el valor cero a __STDC__ para indicar que no son compatibles con ANSI.

C99

Tras el proceso de estandarización de ANSI, la especificación del lenguaje C permaneció relativamente estable durante algún tiempo, mientras que C++ siguió evolucionando. Sin embargo, el estándar continuó bajo revisión a finales de la década de 1990, lo que llevó a la publicación del estándar ISO 9899:1999 en 1999. Este estándar se denomina habitualmente "C99". Se adoptó como estándar ANSI en marzo de 2000.

Las nuevas características de C99 incluyen:

  • Funciones inline.
  • Las variables pueden declararse en cualquier sitio (como en C++), en lugar de poder declararse sólo tras otra declaración o al comienzo de una declaración compuesta.
  • Muchos tipos de datos, incluyendo long long int (para reducir el engorro de la transición de 32 bits a 64 bits), un tipo de datos booleano, y un tipo complex que representa números complejos.
  • Arrays de longitud variable.
  • Soporte para comentarios de una línea que empiecen con //, como en BCPL o en C++, característica para la que muchos compiladores habían dado soporte por su cuenta.
  • muchas funciones nuevas, como snprintf()
  • muchos headers nuevos, como stdint.h.

Una consideración importante es que hasta la publicación de este estándar, C había sido mayormente un subconjunto estricto del C++. Era muy sencillo "actualizar" un programa de C hacia C++ y mantener ese código compilable en ambos lenguajes. Sin embargo, el nuevo estándar agrega algunas características que C++ no admite, como por ejemplo los inicializadores estáticos de estructuras. También define al tipo "bool" de una manera que no es exactamente la del C++.

El compilador GCC, entre muchos otros, soportan hoy en día la mayoría de las nuevas características de C99. Sin embargo, este nuevo estándar ha tenido peor acogida entre algunos desarrolladores de compiladores, como Microsoft y Borland, que se han centrado en C++. Brandon Bray, de Microsoft, dijo a este respecto: "En general, hemos visto poca demanda de muchas características de C99. Algunas características tienen más demanda que otras, y consideraremos incluirlas en versiones futuras siempre que sean compatibles con C++." [1]

Ventajas

  • Lenguaje muy eficiente puesto que es posible utilizar sus características de bajo nivel para realizar implementaciones óptimas.
  • A pesar de su bajo nivel es el lenguaje más portado en existencia, habiendo compiladores para casi todos los sistemas conocidos.
  • Proporciona facilidades para realizar programas modulares y/o utilizar código o bibliotecas existentes.

Desventajas

El mayor problema que presenta el desarrollo con el lenguaje C frente a los lenguajes de tipo de dato dinámico es su gran diferencia de velocidad de desarrollo, siendo mucho más lento desarrollando en C. En cambio, los programas terminados presentan una mejor utilización de los recursos hardware. El mantenimiento también es más difícil y costoso que con el resto de lenguajes. Por otra parte, la mayor parte de los problemas de seguridad en los sistemas informáticos actuales deriva del hecho de que han sido realizados en C: al no disponer de sistemas de control y depender casi exclusivamente de la experiencia del programador, muchas veces quedan algunas entradas de información al programa sin comprobar en su longitud, provocando la sobreescritura de código en la pila del programa. Los lenguajes de tipo dinámico cuentan con muchos más controles de gestión de memoria y de entrada de datos.

Por ello, los directores de desarrollo deben decidir si compensa un desarrollo más largo frente a un peor aprovechamiento del hardware y, teniendo en cuenta además, que el hardware, a igualdad de prestaciones, baja su precio con el tiempo, mientras que el coste de los programadores, aumenta.

Variantes

Desde el inicio del lenguaje han surgido varias ramas de evolución que han generado varios lenguajes:

También se han creado numerosos lenguajes inspirados en la sintaxis de C, pero que no son compatibles con él:

Proceso de compilación

La compilación de un programa C se realiza en varias fases que normalmente son automatizadas y ocultadas por los entornos de desarrollo:

  1. Preprocesado consistente en modificar el código fuente en C según una serie de instrucciones (denominadas directivas de preprocesado) simplificando de esta forma el trabajo del compilador. Por ejemplo, una de las acciones más importantes es la modificación de las inclusiones (#include) por las declaraciones reales existentes en el fichero indicado.
  2. Compilación que genera el código objeto a partir del código ya preprocesado.
  3. Enlazado que une los códigos objeto de los distintos módulos y bibliotecas externas (como las bibliotecas del sistema) para generar el programa ejecutable final.

Ejemplo de código

El siguiente programa imprime en pantalla la frase "Hola Mundo" (C99).

#include <stdio.h> // necesario para utilizar printf()

int main(void)
{
	printf("Hola, Mundo\n");
	// return 0 implícito en C99 para main().
}

El siguiente escribe "Hola, mundo" en C89

/* comentarios con '//' no permitidos en C89, sí en C99 */
#include <stdio.h>  /* necesario para utilizar printf */

main() /* tipo 'int' de retorno implícito */
{
	printf ("Hola Mundo\n") ;
	return 0;
}

Herramientas de programación

Al programar en C, es habitual usar algunas herramientas de programación de uso muy extendido, sobre todo en entorno de tipo unix:

  • make: Herramienta para automatizar el proceso de compilación, enlazado, etc.
  • lint: Herramienta utilizada para detectar código sospechoso, confuso o incompatible entre distintas arquitecturas

Aplicabilidad

Hecho principalmente para la fluidez de programación en sistemas UNIX. Se usa también para el desarrollo de otros sistemas operativos como Windows o Linux. Igualmente para aplicaciones de escritorio como OpenOffice.org, que usa una gran cantidad de miles de líneas de código de más de siete lenguajes distintos, en el que el principal es el C.

De la misma forma, es muy usado en aplicaciones científicas (para experimentos informáticos, físicos, químicos, matemáticos, entre otros, parte de ellos conocidos como modelos y simuladores), industriales (industria robótica, cibernética, sistemas de información y base de datos para la industria petrolera y petroquímica, predominan también todo lo que se refiere a simulación de máquinas de manufactura), simulaciones de vuelo (es la más delicada, ya que se tienen que usar demasiados recursos tanto de hardware como de software para desarrollar aplicaciones que permitan simular el vuelo real de un avión, o bien, de un helicóptero por ejemplo); es decir, se aplica en diversas áreas desconocidas por gran parte de los usuarios noveles.

Aunque los lenguajes de tipo dinámico (Ruby, Python, Perl...) están quitándole mercado, debido sobre todo a la mayor potencia de las máquinas actuales, se puede seguir encontrando grandes desarrollos de animaciones, modelados y renderizados 3D en películas (principalmente; también se puede hacer lo mismo en una enciclopedia multimedia por ejemplo para presentar modelos 3D de partes del cuerpo humano, y así otros ejemplos) de su clase.

Actualmente, los grandes proyectos de software se dividen en partes, dentro de un equipo de desarrollo. Aquellas partes que son más "burocráticas" o "de gestión" con los recursos del sistema, se suelen realizar en lenguajes de tipo dinámico o script, mientras que aquellas partes "críticas", por su necesidad de rapidez de cálculo, se realizan en un lenguaje de tipo compilado, como en C o C++. Si, después de hacer la división, las partes críticas no superan un cierto porcentaje del total (aproximadamente el 10%) entonces todo el desarrollo se realiza con lenguajes dinámicos. Si la parte crítica no llega a cumplir las expectativas del proyecto, se mira a ver si merece hacerse una inversión en un nuevo hardware antes que en invertir en el coste de un programador para que reescriba esa parte crítica.

Biblioteca C

Una biblioteca de C es una colección de bibliotecas utilizadas en el lenguaje de programación C.

Las bibliotecas más comunes son la biblioteca estándar de C y la ISO y estándar ANSI C provee las especificaciones de los estándares, las cuales son ampliamente compartidas entre bibliotecas. La biblioteca ANSI C estándar incluye rutinas para la entrada y salida de archivos, alojamiento de memoria y operaciones con datos comunes como funciones matemáticas, funciones de cadenas y funciones de hora y fecha.

Otros juegos de bibliotecas C son aquellas utilizadas para desarrollar sistemas Unix, las cuales proveen interfaces hacia el núcleo. Estas funciones son detalladas en varios estándares tales como POSIX y el Single UNIX Specification.

Ya que muchos programas han sido escritos en el lenguaje C existe una gran variedad de bibliotecas disponibles. Muchas bibliotecas son escritas en C debido a que C genera código objeto rápido; los programadores luego generan interfaces a la biblioteca para que las rutinas puedan ser utilizadas desde lenguajes de mayor nivel, tales como Java, Perl y Python.

Véase también

Enlaces externos