Abgesehen von Maschinencode gibt es keine Programmiersprache, die direkt auf der Hardware ausgeführt wird, in dem Sinne, dass Sie den wörtlichen Quelltext nicht eingeben können. Alle realen Implementierungen müssen übersetzen das Quellprogramm in die Sprache der „Maschine“.
Bei einigen Implementierungen wird es statisch übersetzt. Wir bezeichnen diese Implementierungen normalerweise als "kompiliert". Für andere wird es in eine Zwischenform übersetzt, die dann dynamisch übersetzt wird, wenn das Programm ausgeführt wird. Wir bezeichnen diese Implementierungen normalerweise als "interpretiert". Dazwischen gibt es eine Fülle von Möglichkeiten, und selbst viele moderne CPUs übersetzen dynamisch als Teil ihres Ausführungskerns.
Selbst wenn Ihr Programm lange vor der Ausführung statisch kompiliert wird, kommt es selten vor, dass der kompilierte Code direkt auf dem Bare-Metal-Computer ausgeführt wird, ohne dass dies unterstützt wird. Das Betriebssystem bietet eine virtuelle Maschine für User-Space-Programme, die häufig Funktionen wie die Illusion bereitstellt, dass Sie eine CPU für sich alleine haben. Die Illusion eines flachen Speicherplatzes, der größer sein könnte als der physische RAM, der an die Maschine angeschlossen ist, wird sogar als "virtueller Speicher" bezeichnet.
Darüber hinaus gibt es eine virtuelle C-Maschine, auch wenn Sie in C programmieren! Es wird traditionell als "C-Laufzeit" oder kurz CRT bezeichnet.
Da C meistens weit im Voraus direkt in Assembly- / Maschinencode übersetzt wird (auf einigen Plattformen kann es auch Thread-Code geben , der als Teil der virtuellen Maschine betrachtet werden kann), muss die virtuelle Maschine in der Regel nur den Start und die Ausführung übernehmen Herunterfahren.
Beim Start werden in der Regel der Stack und der Heap eingerichtet. Das Betriebssystem stellt diese selten zur Verfügung, und es ist Aufgabe der Programmiersprache, sie dem Programmierer zur Verfügung zu stellen. Auf einigen Plattformen wird möglicherweise die Signalverarbeitung initialisiert, der "Haupt" -Thread wird in einer Umgebung mit mehreren Threads eingerichtet, globale Konstruktoren werden ausgeführt, wenn nicht die Wahrscheinlichkeit besteht, dass das Programm mit C ++ - Code verknüpft wurde, und dynamisch verknüpfte Bibliotheken werden verarbeitet Möglicherweise ist eine gewisse Verarbeitung erforderlich, um argc / argv und envp einzurichten. Schließlich übergibt CRT die Kontrolle an main.
Beim Herunterfahren können viele Betriebssysteme einen Prozess unsauber beenden, sodass beim Herunterfahren nicht viel getan werden muss. Die Hauptsache ist, atexit () -Aufrufe für den Fall zu verarbeiten, dass das Programm sauber beendet wird.