Además del código de máquina, no existe un lenguaje de programación que se ejecute directamente en el hardware, en el sentido de que no puede alimentarlo con el texto fuente literal. Todas las implementaciones reales deben traducir el programa fuente al lenguaje de la "máquina".
Para algunas implementaciones, se traduce estáticamente. Generalmente llamamos a estas implementaciones "compiladas". Para otros, se traduce a alguna forma intermedia, que luego se traduce dinámicamente a medida que se ejecuta el programa. Generalmente llamamos a estas implementaciones "interpretadas". Hay un continuo de posibilidades entre estos, e incluso muchas CPU modernas hacen una traducción dinámica como parte de su núcleo de ejecución.
Incluso cuando su programa se compila estáticamente mucho antes de la ejecución, a menos que esté escribiendo firmware, es raro que el código compilado se ejecute directamente en el metal desnudo sin nada que lo soporte. El sistema operativo proporciona una máquina virtual para programas de espacio de usuario, a menudo brinda características tales como la ilusión de que tienes una CPU para ti. La ilusión de un espacio de memoria plana que podría ser más grande que la RAM física conectada a la máquina incluso se llama "memoria virtual".
Además de eso, incluso cuando está programando en C, ¡hay una máquina virtual en C! Tradicionalmente se conoce como "el tiempo de ejecución C" o CRT para abreviar.
Debido a que C se traduce principalmente directamente en el código de ensamblaje / máquina con mucha anticipación (en algunas plataformas, también puede haber algún código enhebrado , y eso puede considerarse parte de la máquina virtual), la máquina virtual generalmente solo tiene que manejar el inicio y apagar.
El inicio generalmente implica la configuración de la pila y el montón; el sistema operativo rara vez proporciona estos para usted, y el trabajo del lenguaje de programación es proporcionarlos al programador. En algunas plataformas puede haber alguna inicialización del manejo de la señal, configurando el subproceso "principal" en un entorno de subprocesos múltiples, ejecutando constructores globales en caso de que el programa se haya vinculado al código C ++, manejando bibliotecas vinculadas dinámicamente, o allí Es posible que se requiera algún procesamiento para configurar argc / argv y envp. Finalmente, CRT transfiere el control a main.
En cuanto al apagado, muchos sistemas operativos pueden matar un proceso sin limpieza, por lo que el apagado no necesita hacer mucho. Lo principal es procesar llamadas atexit () para el caso en que el programa salga limpiamente.