Al igual queB, es un lenguaje orientado a la implementación desistemas operativos; concretamenteUnix.C es apreciado por la eficiencia del código que produce y es el lenguaje de programación más popular para crearsoftwares de sistemas yaplicaciones.
Se trata de un lenguaje del tipo datos estáticos, débilmente tipado, que dispone de las estructuras típicas de loslenguajes de alto nivel, pero, a su vez, dispone de construcciones del lenguaje que permiten un control abajo nivel, lo que lo convierte en un lenguaje de nivel medio. Los compiladores suelen ofrecer extensiones al lenguaje que posibilitan mezclar código enensamblador con código C o acceder directamente amemoria odispositivos periféricos.
La primera estandarización del lenguaje C fue enANSI, con el estándar X3.159-1989. El lenguaje que define este estándar fue conocido vulgarmente comoANSI C. Posteriormente, en 1990, fue ratificado como estándarISO (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 portable entre plataformas y/oarquitecturas.
Uno de los objetivos de diseño del lenguaje C es que solo sean necesarias pocas instrucciones enlenguaje máquina para traducir cada elemento del lenguaje, sin que haga 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 (más que cualquier otro lenguaje). Además, a pesar de su naturaleza de nivel medio, 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 operativoUnix, 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 laprogramación desoftware de sistema, para la que se diseñó originalmente.
Núcleo del lenguaje simple, con funcionalidades añadidas importantes, como funciones matemáticas y degestión de archivos, proporcionadas porbibliotecas.
Es unlenguaje estructurado; tiene estructuras de control y tipos de datos estructurados definidos por el programador a partir de los tipos atómicos típicos y mediante arreglos, estructuras, uniones ypunteros, incluidos los que apuntan a una función.
En su primera edición no había advertencias sobre asignar a una variable un valor un tipo distinto. Por lo que había un programa llamadolint que detectaba este tipo de errores. Actualmente los compiladores pueden detectar inconsistencias de tipos y otros errores.
El llamado a funciones es por valor. Aunque se pueden pasar punteros a variables para hacer llamados por referencia.
Distintos tipos de almacenamiento que permiten un diseño modular.
La palabra clave struct permite encapsular variables y funciones.
Lenguaje muy eficiente puesto que es posible utilizar sus características de bajo nivel para realizar implementaciones óptimas.
Se diseñó como un lenguaje de programación de sistemas portátil.
Es muy poco lo que requiere uso de ensamblador, lo que permitió portar Unix y otros sistemas operativos a distintos equipos.
Distingue entre mayúsculas y minúsculas, pero conserva su portabilidad en equipos que manejan caracteres de 6 bits, como las computadorasCyber deCDC que tenían una palabra de 60 bits, (10 caracteres), porque usan gráficos para codificar símbolos especiales.
Su compilador de C se ha portado a la mayoría de sistemas. Porque además de que no se requiere codificar en ensamblador, interactúa con los lenguajes especializados YACC y Alex. también escritos en C como parte de Unix.
Facilita la programación modular gracias a que cuenta con distintos tipos de almacenamiento de las variables y compilación separada. Esto se logra mediante la inclusión de ficheros cabecera .h mediante la directiva de preprocesador#include.
extern sirve para declarar objetos externos que se usarán en el programa pero que no se encuentran en el fichero del programa, por lo que es necesario pasar los nombres de los ficheros como parámetros del enlazador.
Los programadores novatos deben tener cuidado con la gestión de la memoria; en C el programador ha de reservar y liberar la memoria explícitamente. En otros lenguajes (como C# o Java) la memoria es gestionada de forma transparente para el programador. Esto alivia la carga de trabajo y evita errores, pero le quita flexibilidad al lenguaje para escribir controladores del hardware.
Por esta razón es muy importante que los recién iniciados adopten buenas prácticas a la hora de escribir en C y manejar la memoria, como por ejemplo un uso intensivo deindentación y conocer a fondo todo lo que implica el manejo de punteros y direcciones de memoria.
Soporte paraprogramación orientada a objetos, aunque la implementación original deC++ fue un preprocesador que traducía código fuente de Quer Véase también la libreríaGObject.
Unidadas, aunqueGCC tiene esta característica como extensión.
Soporte nativo para programaciónmultihilo. Disponible usando librerías comolibretad.
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 nuevoscompiladores 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. Esta es la causa de que a menudo C sea más eficiente que otros lenguajes. Típicamente, solo la programación cuidadosa enlenguaje 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 losmicroprocesadores modernos han reducido gradualmente esta diferencia.
El lenguaje se puede extender mediante bibliotecas y macros. Por ejemplo, la implementación original deC++ consistía en un preprocesador que traducía código fuente C++ a C.
El desarrollo inicial de C se llevó a cabo en losLaboratorios Bell deAT&T entre 1969 y 1973; segúnDennis Ritchie, el periodo más creativo tuvo lugar en 1972.[1] 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 conSpace Travel. Habían estado jugando en launidad central de su compañía, pero debido a su poca capacidad de proceso y al tener que soportar 100 usuarios,Ken Thompson yDennis Ritchie no tenían suficiente control sobre la nave para evitar colisiones con los asteroides, por ese motivo decidieron portar el juego a unPDP-7 de la oficina que no se utilizaba; pero esa máquina no teníasistema operativo, así que decidieron escribir uno. Finalmente decidieron portar el sistema operativo delPDP-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 delkernel Unix, originalmente escrito en el lenguaje ensamblador PDP-11, fue reescrita en C.[1] Este fue uno de los primeros núcleos de sistema operativo implementados en un lenguaje distinto al ensamblador. (Algunos casos anteriores son el sistemaMultics, escrito enPL/I, yMaster Control Program para elB5000 de Burroughs, escrito enALGOL en 1961).
En 1978,Ritchie yBrian Kernighan publicaron la primera edición deEl lenguaje de programación C, también conocido como «La biblia de C». Este libro fue durante años laespecificación informal del lenguaje.[2]: 2 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ándarANSI C, descrito más adelante en este artículo).
Kernighan yRitchie introdujeron las siguientes características al lenguaje:
El tipo de datosstruct.
El tipo de datoslong int.
El tipo de datosunsigned int.
Los operadores=+ y=- fueron sustituidos por+= y-= para eliminar la ambigüedad sintáctica de expresiones comoi=-10, que se podría interpretar bien comoi =- 10 o bien comoi = -10.
El C deKernighan yRitchie es el subconjunto más básico del lenguaje que un compilador debe de soportar. Durante muchos años, incluso tras la introducción delANSI 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ódigoANSI C válido.
En las primeras versiones del lenguaje, la definición de funciones se hacía mediante un 'prototipo de función' (function prototype), el cual indicaba al compilador el tipo de retorno de la función. Aunque este método tiene una gran desventaja respecto al nuevo, debido a que no comprueba el número ni el tipo en la lista de argumentos; en otras palabras, es mucho más fácil cometer errores al hacer una llamada a una función con argumentos incorrectos.
Ejemplo del «viejo estilo»:
intpower();/* Se podría usar este prototipo para llamar a la función. Simplemente power(); u omitirlo dado que el tipo por default es int */power(a,b)inta,b;{intn;for(n=2;b>0;--b)n*=a;returnn;}
(*) Por defecto, el tipo de retorno en C es int, por lo que la declaración enteraint power(); podría haberse omitido.
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 estaban soportadas por los compiladores de AT&T, entre otros. Algunas de estas características eran:
Funcionesvoid y el tipo de datosvoid *.
Funciones que retornaban tipos de datosstruct ounion (en lugar de punteros).
Asignación de tipos de datosstruct.
Calificadorconst, que hace que un objeto sea de solo lectura.
Unabiblioteca estándar, que incorporaba la mayoría de las funcionalidades implementadas por varios desarrolladores de compiladores.
A finales de la década de 1970, C empezó a sustituir aBASIC como lenguaje de programación de microcomputadores predominante. Durante la década de 1980 se empezó a usar en losIBM 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, llamadoC++, es hoy en día el lenguaje de programación de aplicaciones más común en el sistema operativoMicrosoft 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 aplicacionesCocoa paraMac OS X.
En 1983, elInstituto Nacional Estadounidense de Estándares (ANSI) 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 comoANSI C, o a veces como C89 (para distinguirla de C99).
En 1990, el estándar ANSI (con algunas modificaciones menores) fue adoptado por laOrganizació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)intargc;char**argv;{...}
pasó a ser:
intmain(intargc,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 escritosó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 solo 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áficas 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__externintgetopt(int,char*const*,constchar*);# elseexternintgetopt();# 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.
En el siguiente ejemplo, el programa pide al usuario que introduzca un número. El programa dividirá dicho número entre 2 e imprimirá el resultado mientras que este sea par, y terminará cuando el número sea impar:
#include<stdio.h>intmain(){intnumero;fputs("Introduzca un numero entero par: ",stdout);if(scanf("%d",&numero)!=1){fputs("Error: numero no valido.\n",stderr);return-1;}for(inti=2;numero%2==0;++i){printf("%.3d| %d/2 = ",i,numero);numero/=2;printf("%d\n",numero);}printf("No se puede seguir dividiendo: El numero %d es impar.\n",numero);getchar();return0;}
Tras el proceso de estandarización de ANSI, la especificación del lenguaje C permaneció relativamente estable durante algún tiempo, mientras queC++ 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.[5] Este estándar se denomina habitualmente «C99». Se adoptó como estándar ANSI en marzo de 2000.
Las nuevas características de C99 incluyen:[6]: xi–xii
Lasvariables pueden declararse en cualquier sitio (como en C++), en lugar de poder declararse solo tras otra declaración o al comienzo de una declaración compuesta.
Muchos tipos de datos, incluyendolong int (para reducir el engorro de la transición de 32 bits a 64 bits), un tipo de datobooleano, y un tipocomplex que representanúmeros complejos.
Soporte para comentarios de una línea que empiecen con//, como enBCPL o en C++, característica para la que muchos compiladores habían dado soporte por su cuenta.
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 poca acogida entre algunos desarrolladores de compiladores, comoMicrosoft yBorland, 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++.[7]
C11 (antes conocido comoC2X) es un nombre informal paraISO/IEC 9899:2011[8]. El borrador final, N1570, fue publicado en abril de 2011.[9] El nuevo estándar superó su última revisión el 10 de octubre de 2011 y fue oficialmente ratificado por la ISO y publicado el 8 de diciembre de 2011.
Históricamente la programación en C embebido ha requerido extensiones no estándar del lenguaje C para implementar características no oficiales tales como aritmética de punto fijo y operaciones básicas de entrada y salida.
En 2008 el comité de estandarización de C, para implementar estas características no oficiales, publicó un informe técnico en el que extendía el lenguaje C proporcionando un estándar común al que todas las implementaciones se podían adherir. Incluía varias características no disponibles en C normal, tales como aritmética de punto fijo, espacios de direcciones con nombres y direccionamiento por hardware de entrada y salida básico.
C++ (pronunciadoC Plus Plus) diseñado porBjarne Stroustrup fue el segundo intento de proporcionarorientación a objetos a C y es la variante más difundida y aceptada. Esta versión combina la flexibilidad y el acceso de bajo nivel de C con las características de la programación orientada a objetos como abstracción, encapsulación y ocultación.
También se han creado numerosos lenguajes inspirados en la sintaxis de C, pero que no son compatibles con él:
Java, que une una sintaxis inspirada en la del C++ con una orientación a objetos más similar a la deSmalltalk yObjective C.
JavaScript, un lenguaje descripting creado enNetscape e inspirado en la sintaxis de Java diseñado para dar a laspáginas web mayor interactividad. A la versión estandarizada se la conoce comoECMAScript.
C# (pronunciadoC Sharp) es un lenguaje desarrollado porMicrosoft derivado de C/C++ yJava.
Lacompilació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 elcódigo fuente en C según una serie de instrucciones (denominadasdirectivas de preprocesado) simplificando de esta forma el trabajo delcompilador. Por ejemplo, una de las acciones más importantes es la modificación de las inclusiones (#include) por las declaraciones reales existentes en el archivo indicado.
El siguiente programa imprime en pantalla la frase «Hola Mundo» (C99):
// necesario para utilizar printf()#include<stdio.h>intmain(void){printf("Hola Mundo\n");return0;}
El siguiente programa muestra el uso depunteros en C:
#include<stdio.h>intmain(){// Variableintnumero=99;// Puntero a variableint*p;// Asignación de punterop=№// Acceso al valor de la variable a la que apunta el punteroprintf("Numero: %d\n",*p);// Acceso a la dirección a la que apunta el punteroprintf("Direccion: %d\n",p);// Cambio de valor de la variable a la que apunta el puntero*p=2;printf("Numero: %d\n",numero);}
/* 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");return0;}
El lenguaje de programación C y su relación con otras plataformas informáticas que se basan en él.
El lenguaje de programación C está hecho principalmente para la fluidez deprogramación en los sistemasUnix, aunque también se usa para el desarrollo de otrossistemas operativos comoWindows oGNU/Linux y para aplicaciones deescritorio comoGIMP, cuyo principal lenguaje de programación es C.
Los ordenadores de finales de los 90 son varios órdenes de magnitud más potentes que las máquinas en que C se desarrolló originalmente. Programas escritos en lenguajes de tipo dinámico y fácil codificación (Ruby,Python,Perl, etc.) que antaño hubieran resultado demasiado lentos, son lo bastante rápidos como para desplazar en uso a C. Aun así, se puede seguir encontrando código C en grandes desarrollos deanimaciones, modelados yescenas en 3D enpelículas y otras aplicacionesmultimedia.
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 de guion (script), mientras que aquellas partes «críticas», por su necesidad de rapidez de ejecución, se realizan en un lenguaje de tipo compilado, como 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 comparan las alternativas de una inversión en nuevo hardware frente a invertir en el coste de un programador para que reescriba dicha parte crítica.
C es el lenguaje común para programarsistemas embebidos.[cita requerida] El código ligero que un compilador C genera, combinado con la capacidad de acceso a capas del software cercanas al hardware son la causa de su popularidad en estas aplicaciones.
Una característica donde C demuestra comodidad de uso particularmente valiosa en sistemas embebidos es la manipulación de bits. Los sistemas contienenregistros mapeados en memoria (en inglés, MMR) a través de los cuales los periféricos se configuran. Estos registros mezclan varias configuraciones en la misma dirección de memoria, aunque en bits distintos. Con C es posible modificar fácilmente uno de estos bits sin alterar el resto. Por ejemplo:
int*mmr;/* puntero al registro que queremos modificar */mmr=0x40008ABC;/* dirección de memoria del registro */*mmr|=1<<7;/* pone a 1 el bit 8 sin modificar los demás */*mmr&=~(1<<12)/* pone a 0 el bit 13 sin modificar los demás */
Este tipo de manipulación es muy tediosa o sencillamente imposible en otros lenguajes de alto nivel, dado que se utilizan operaciones comunes dellenguaje ensamblador como lasoperaciones a nivel bit OR, AND, SHL y CPL pero que están disponibles en el lenguaje C.
Otras características de C consideradas desventajas en la programación para PC -como la ausencia de control de memoria automático- se convierten en ventajas cuando los sistemas embebidos necesitan código pequeño y optimizado. Ese es el caso de los sistemas basados en microcontroladores de poca potencia como elintel 8051 o muchos sistemasARM.
Una biblioteca de C es una colección de funciones utilizadas en el lenguaje de programación C. Las bibliotecas más comunes son labiblioteca estándar de C y la biblioteca delestándar ANSI C, la cual provee las especificaciones de los estándares que son ampliamente compartidas entre bibliotecas. Labiblioteca ANSI C estándar, incluye funciones para la entrada y salida de archivos, alojamiento de memoria y operaciones con datos comunes: funciones matemáticas, funciones de manejo de cadenas de texto y funciones de hora y fecha.
Otras bibliotecas C son aquellas utilizadas para desarrollar sistemasUnix, las cuales proveen interfaces hacia elnúcleo. Estas funciones son detalladas en varios estándares tales comoPOSIX y elSingle 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 generacó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 comoJava,Perl yPython.