Los ordenadores digitales no entienden los lenguajes que hablan los humanos. En su lugar, utilizan un lenguaje binario llamado código de máquina o lenguaje de máquina.El código de máquina consiste en una secuencia de instrucciones simples de ordenador con cada instrucción expresada como una cadena de dígitos binarios o bits (es decir, 1’s y 0’s). Los distintos ordenadores suelen «hablar» o «entender» diferentes lenguajes de máquina. Por ejemplo, un ordenador puede representar la operación ADD como 10011111
mientras que otro puede representar las mismas operaciones como 000110
. No sólo los patrones de bits son diferentes de un tipo de ordenador a otro, sino que incluso el número de bits utilizados para representar una operación puede ser diferente.
Además, cuando se ejecuta un programa, el sistema operativo (por ejemplo, Windows, Linux, OS X, etc.) actúa como un entorno anfitrión que proporciona servicios al programa. Lamentablemente, la forma en que el programa accede a esos servicios también es diferente de un sistema operativo a otro. Como resultado de las diferencias entre los lenguajes de máquina y los requisitos del sistema operativo, los programas escritos en lenguaje de máquina se centran más en el sistema que ejecuta el programa que en la forma en que éste resuelve un problema. Además, también significa que no es posible trasladar el código máquina entre diferentes ordenadores sin proporcionar algún tipo de servicio de traducción – normalmente en forma de máquina virtual.
Escribir programas en lenguaje máquina es lento, tedioso y propenso a errores. La solución fue desarrollar lenguajes de programación de alto nivel que se centraran más en el problema y menos en el sistema (el hardware y el sistema operativo) que ejecutaba el programa (véase la figura 2). Pero los ordenadores no suelen ejecutar programas escritos en lenguajes de alto nivel, por lo que debe haber alguna forma de traducir un programa escrito en un lenguaje de alto nivel al lenguaje de la máquina. Hay dos tipos de programas informáticos que realizan la traducción necesaria: los compiladores y los intérpretes.
Un compilador es un programa que traduce otros programas escritos en un lenguaje de programación de alto nivel, como C o C++, a código máquina o lenguaje de máquina.Otros lenguajes, como Java y C#, toman un camino diferente: Los programas escritos en estos lenguajes se compilan a una representación intermedia (una representación que se encuentra en algún lugar entre el lenguaje de alto nivel y el lenguaje de máquina) que suele llamarse código de máquina virtual. El código de la máquina virtual se convierte entonces en la entrada de otro programa llamado intérprete o máquina virtual (VM, un programa que simula una CPU de hardware). Algunos lenguajes, como Javascript y Perl, son completamente interpretados, es decir, no se compilan sino que se interpretan directamente.
Cada enfoque para ejecutar un programa escrito en un lenguaje de programación de alto nivel tiene ventajas y desventajas. Los programas escritos en lenguajes totalmente compilados (por ejemplo, C y C++) se ejecutan más rápido que los programas escritos en lenguajes parcialmente compilados (por ejemplo, Java y C#) y se ejecutan mucho más rápido que los programas escritos en lenguajes totalmente interpretados (por ejemplo, Javascript y Perl). Para dar una idea de la diferencia de rendimiento, digamos que un programa en C++, una vez compilado, se ejecuta en tiempo 1,0. Un programa equivalente escrito en un lenguaje que se compila y luego se interpreta se ejecutará generalmente en un tiempo de 3 a 10. El mismo programa ejecutado en un lenguaje puramente interpretado se ejecutará en un tiempo de unos 100. Las implementaciones contemporáneas de las máquinas virtuales de Java y C# utilizan un intérprete justo a tiempo (JIT) que compila parte del código virtual a código máquina mientras lo procesa. Los procesadores JIT reducen el tiempo de ejecución a aproximadamente 1,5 veces el de los sistemas de lenguaje puramente compilado. El lenguaje de programación Python es un poco diferente: la parte principal de un programa Python se interpreta, pero es relativamente pequeña, por lo que tiene un impacto mínimo en el tiempo de ejecución general. La mayoría de las bibliotecas de Python, donde el programa pasa la mayor parte de su tiempo, están escritas en C, por lo que los programas de Python se ejecutan casi tan rápido como un programa equivalente en C.
Por otro lado, los programas ejecutables producidos por un compilador puro no pueden transferirse entre plataformas distintas (por ejemplo, no se puede ejecutar un programa de Windows en un ordenador de Apple), mientras que los programas escritos en lenguajes interpretados son más fáciles de trasladar entre distintos ordenadores. Esta portabilidad se consigue proporcionando una VM o un intérprete para cada plataforma (combinación de hardware y sistema operativo). Los intérpretes y las VM son programas que están escritos en lenguajes puramente compilados, por lo que no son portables, pero los programas que procesan sí lo son.