Kompilierte vs. interpretierte Sprachen

284

Ich versuche, den Unterschied besser zu verstehen. Ich habe online viele Erklärungen gefunden, aber sie tendieren eher zu den abstrakten Unterschieden als zu den praktischen Implikationen.

Die meisten meiner Programmiererfahrungen habe ich mit CPython (dynamisch, interpretiert) und Java (statisch, kompiliert) gemacht. Ich verstehe jedoch, dass es andere Arten von interpretierten und kompilierten Sprachen gibt. Gibt es neben der Tatsache, dass ausführbare Dateien aus Programmen verteilt werden können, die in kompilierten Sprachen geschrieben sind, Vor- und Nachteile für jeden Typ? Oft höre ich Leute argumentieren, dass interpretierte Sprachen interaktiv verwendet werden können, aber ich glaube, dass kompilierte Sprachen auch interaktive Implementierungen haben können, richtig?

Chimäre
quelle
32
Sie haben für diesen Vergleich genau die schlechtesten Sprachen ausgewählt. Beide sind bytekompiliert. Der einzige wirkliche Unterschied zwischen ihnen ist der JITer, und sogar Python hat einen Teil (Psyco).
Ignacio Vazquez-Abrams
1
Ein gutes Beispiel für eine interaktive kompilierte Sprache ist Clojure - alles ist vollständig kompiliert (zuerst zur JVM, dann zum nativen Code über die JIT). Ein Großteil der Neukompilierung erfolgt jedoch dynamisch, und die Entwicklung erfolgt häufig in einer interaktiven REPL-Shell, in der Sie jede gewünschte Funktion in der laufenden Umgebung bewerten können.
Mikera
Standard ML ist eine weitere interaktive kompilierte Sprache. Der eingebaute Compiler gibt auch echten nativen Maschinencode aus.
Donal Fellows

Antworten:

459

Eine kompilierte Sprache ist eine Sprache, in der das einmal kompilierte Programm in den Anweisungen des Zielcomputers ausgedrückt wird. Beispielsweise könnte eine zusätzliche "+" - Operation in Ihrem Quellcode direkt in die Anweisung "ADD" im Maschinencode übersetzt werden.

Eine interpretierte Sprache ist ein , wo die Anweisungen nicht direkt von der Zielmaschine ausgeführt, sondern gelesen und durch ein anderes Programm ausgeführt (die in der Regel ist in der Sprache der nativen Maschinen geschrieben). Zum Beispiel würde der Interpreter zur Laufzeit dieselbe "+" - Operation erkennen, die dann seine eigene Funktion "add (a, b)" mit den entsprechenden Argumenten aufruft und dann den Befehl "ADD" des Maschinencodes ausführt .

Sie können alles tun, was Sie in einer interpretierten Sprache in einer kompilierten Sprache tun können und umgekehrt - beide sind vollständig. Beide haben jedoch Vor- und Nachteile für die Implementierung und Verwendung.

Ich werde es vollständig verallgemeinern (Puristen verzeihen mir!), Aber ungefähr hier sind die Vorteile kompilierter Sprachen:

  • Schnellere Leistung durch direkte Verwendung des nativen Codes des Zielcomputers
  • Möglichkeit, während der Kompilierungsphase recht leistungsstarke Optimierungen anzuwenden

Und hier sind die Vorteile interpretierter Sprachen:

  • Einfacher zu implementieren (gute Compiler zu schreiben ist sehr schwer !!)
  • Keine Kompilierungsphase erforderlich: Code kann direkt "on the fly" ausgeführt werden.
  • Kann für dynamische Sprachen bequemer sein

Beachten Sie, dass moderne Techniken wie die Bytecode-Kompilierung eine zusätzliche Komplexität verursachen. Was hier passiert, ist, dass der Compiler auf eine "virtuelle Maschine" abzielt, die nicht mit der zugrunde liegenden Hardware identisch ist. Diese Anweisungen für virtuelle Maschinen können dann zu einem späteren Zeitpunkt erneut kompiliert werden, um nativen Code abzurufen (z. B. wie vom Java JVM JIT-Compiler ausgeführt).

mikera
quelle
1
Nicht alle kompilierten Sprachen benötigen eine langsame Kompilierungsphase. Serious Common Lisp-Implementierungen sind Compiler, und sie kümmern sich oft nicht um einen Interpreter. Sie ziehen es vor, nur sehr schnell im laufenden Betrieb zu kompilieren. Auf der anderen Seite benötigt Java einen Kompilierungsschritt, der normalerweise sichtbar ist.
David Thornley
2
@Kareem: Der JIT-Compiler führt 1) und 2) nur einmal aus - danach handelt es sich vollständig um nativen Code. Der Interpreter muss bei jedem Aufruf des Codes sowohl 1) als auch 2) ausführen (dies kann viele, viele Male sein ...). Mit der Zeit gewinnt der JIT-Compiler also mit großem Abstand.
Mikera
3
Ja, Bytecode wird irgendwann während der gesamten Programmausführung in Maschinencode übersetzt (im Gegensatz zu vor der Programmausführung, wie dies bei einem herkömmlichen Compiler der Fall ist). Ein bestimmter Code kann jedoch während der gesamten Programmausführung mehr als 10 Millionen Mal ausgeführt werden. Es wird (wahrscheinlich) nur einmal vom Bytecode zum Maschinencode kompiliert. Daher ist der Laufzeitaufwand von JIT gering und kann für Programme mit langer Laufzeit ignoriert werden. Nachdem der JIT-Compiler seine Arbeit beendet hat, führen Sie effektiv reinen Maschinencode aus.
Mikera
2
Dies ist eigentlich eine falsche Zweiteilung. Es gibt nichts, was einer Sprache innewohnt, das sie zu unserer Interpretation zusammenstellt. Es ist nichts weiter als ein weit verbreitetes Missverständnis. Viele Sprachen haben beide Implementierungen und alle Sprachen können beide haben.
mmachenry
2
@mmachenry es ist keine falsche Zweiteilung. "Programmiersprache" umfasst sowohl Design als auch Implementierung. Während im theoretischen Sinne eine bestimmte Sprachdefinition sowohl zusammengestellt als auch interpretiert werden kann, gibt es in der Praxis erhebliche Unterschiede in der Implementierung. Bisher hat noch niemand gelöst, wie bestimmte Sprachkonstrukte effektiv kompiliert werden können - es ist ein offenes Forschungsproblem.
Mikera
99

Eine Sprache selbst wird weder kompiliert noch interpretiert, sondern nur eine bestimmte Implementierung einer Sprache. Java ist ein perfektes Beispiel. Es gibt eine Bytecode-basierte Plattform (JVM), einen nativen Compiler (gcj) und einen Interpeter für eine Obermenge von Java (bsh). Was ist Java jetzt? Bytecode-kompiliert, nativ kompiliert oder interpretiert?

Andere Sprachen, die sowohl kompiliert als auch interpretiert werden, sind Scala, Haskell oder Ocaml. Jede dieser Sprachen verfügt über einen interaktiven Interpreter sowie einen Compiler für Bytecode oder nativen Maschinencode.

Eine allgemeine Kategorisierung von Sprachen nach "kompiliert" und "interpretiert" macht daher wenig Sinn.

Mondhorn
quelle
3
Genau. Oder lassen Sie uns sagen: Es gibt native Compiler (Erstellen von Maschinencode für die CPU) und nicht so native Compiler (Erstellen von tokenisiertem Material, dh Zwischencode, den einige Just-in-Time-Compiler zuvor zu Maschinencode kompilieren ( oder während der Laufzeit EINMAL), und es gibt "echte" Nicht-Compiler, die niemals Maschinencode erzeugen und die CPU niemals den Code ausführen lassen. Letztere sind Dolmetscher. Heutzutage werden native Compiler, die zur Kompilierungszeit direkt Maschinencode (CPU) erzeugen, immer seltener. Delphi / Codegear ist einer der besten Überlebenden.
TheBlastOne
57

Fangen Sie an, in einer Explosion aus der Vergangenheit zu denken

Es war einmal vor langer, langer Zeit, als im Land der Computerinterpreten und Compiler lebte. Es kam zu allerlei Aufhebens um die Verdienste des einen über das andere. Die allgemeine Meinung zu dieser Zeit war etwas in der Art von:

  • Interpreter: Schnell zu entwickeln (bearbeiten und ausführen). Langsame Ausführung, da jede Anweisung bei jeder Ausführung in Maschinencode interpretiert werden musste (denken Sie daran, was dies für eine Schleife bedeutete, die tausendmal ausgeführt wurde).
  • Compiler: Langsam zu entwickeln (bearbeiten, kompilieren, verknüpfen und ausführen. Die Schritte zum Kompilieren / Verknüpfen können einige Zeit in Anspruch nehmen). Schnell auszuführen. Das gesamte Programm befand sich bereits im nativen Maschinencode.

Zwischen einem interpretierten Programm und einem kompilierten Programm bestand ein Unterschied von ein oder zwei Größenordnungen in der Laufzeitleistung. Andere Unterscheidungsmerkmale, beispielsweise die Laufzeitveränderlichkeit des Codes, waren ebenfalls von Interesse, aber die Hauptunterscheidung drehte sich um die Laufzeitleistungsprobleme.

Heute hat sich die Landschaft so weit entwickelt, dass die zusammengestellte / interpretierte Unterscheidung so gut wie irrelevant ist. Viele kompilierte Sprachen rufen Laufzeitdienste auf, die nicht vollständig auf Maschinencode basieren. Außerdem werden die meisten interpretierten Sprachen vor der Ausführung in Bytecode "kompiliert". Bytecode-Interpreter können unter dem Gesichtspunkt der Ausführungsgeschwindigkeit sehr effizient sein und mit einigen vom Compiler generierten Codes konkurrieren.

Der klassische Unterschied besteht darin, dass Compiler nativen Maschinencode generieren, Interpreter Quellcode lesen und Maschinencode im laufenden Betrieb mithilfe eines Laufzeitsystems generieren. Heutzutage gibt es nur noch wenige klassische Interpreter - fast alle kompilieren in Bytecode (oder einen anderen halbkompilierten Zustand), der dann auf einer virtuellen "Maschine" ausgeführt wird.

NealB
quelle
1
Schön - tolle Zusammenfassung im letzten Absatz - danke!
ckib16
26

Die extremen und einfachen Fälle:

  • Ein Compiler erstellt eine ausführbare Binärdatei im nativen ausführbaren Format des Zielcomputers. Diese Binärdatei enthält alle erforderlichen Ressourcen mit Ausnahme der Systembibliotheken. Es kann ohne weitere Vorbereitung und Verarbeitung ausgeführt werden und läuft wie ein Blitz, da der Code der native Code für die CPU auf dem Zielcomputer ist.

  • Ein Dolmetscher zeigt dem Benutzer eine Eingabeaufforderung in einer Schleife an, in die er Anweisungen oder Code eingeben kann, und beim Schlagen RUNoder Äquivalent wird der Dolmetscher jede Zeile untersuchen, scannen, analysieren und interpretativ ausführen, bis das Programm zu einem Haltepunkt oder einem Fehler läuft . Da jede Zeile für sich behandelt wird und der Dolmetscher nichts "lernt", wenn er die Zeile zuvor gesehen hat, fällt jedes Mal für jede Zeile der Aufwand an, eine für Menschen lesbare Sprache in Maschinenanweisungen umzuwandeln, sodass der Hund langsam ist. Auf der positiven Seite kann der Benutzer sein Programm auf verschiedene Arten überprüfen und auf andere Weise mit ihm interagieren: Ändern von Variablen, Ändern von Code, Ausführen im Trace- oder Debug-Modus ... was auch immer.

Lassen Sie mich erklären, dass das Leben nicht mehr so ​​einfach ist. Zum Beispiel,

  • Viele Dolmetscher kompilieren den Code, den sie erhalten, vor, damit der Übersetzungsschritt nicht immer wieder wiederholt werden muss.
  • Einige Compiler kompilieren nicht nach CPU-spezifischen Maschinenanweisungen, sondern nach Bytecode, einer Art künstlichem Maschinencode für eine fiktive Maschine. Dies macht das kompilierte Programm etwas portabler, erfordert jedoch auf jedem Zielsystem einen Bytecode-Interpreter.
  • Die Bytecode-Interpreter (ich sehe hier Java) neigen dazu, den Bytecode, den sie für die CPU des Zielabschnitts erhalten, kurz vor der Ausführung neu zu kompilieren (JIT genannt). Um Zeit zu sparen, wird dies häufig nur für Code ausgeführt, der häufig ausgeführt wird (Hotspots).
  • Einige Systeme, die wie Interpreter aussehen und sich so verhalten (z. B. Clojure), kompilieren jeden Code, den sie erhalten, sofort, ermöglichen jedoch den interaktiven Zugriff auf die Programmumgebung. Das ist im Grunde die Bequemlichkeit von Dolmetschern mit der Geschwindigkeit der binären Kompilierung.
  • Einige Compiler kompilieren nicht wirklich, sondern verarbeiten und komprimieren nur Code. Ich habe vor einiger Zeit gehört, dass Perl so funktioniert. Manchmal macht der Compiler nur einen Teil der Arbeit und das meiste davon ist immer noch Interpretation.

Letztendlich ist das Interpretieren gegenüber dem Kompilieren heutzutage ein Kompromiss, da die (einmalige) Kompilierungszeit häufig durch eine bessere Laufzeitleistung belohnt wird, aber eine interpretative Umgebung, die mehr Interaktionsmöglichkeiten bietet. Beim Kompilieren und Dolmetschen geht es hauptsächlich darum, wie die Arbeit zum "Verstehen" des Programms auf verschiedene Prozesse aufgeteilt wird, und die Linie ist heutzutage etwas verschwommen, da Sprachen und Produkte versuchen, das Beste aus beiden Welten anzubieten.

Carl Smotricz
quelle
23

Von http://www.quora.com/Was ist der Unterschied zwischen kompilierten und interpretierten Programmiersprachen?

Es gibt keinen Unterschied, da „kompilierte Programmiersprache“ und „interpretierte Programmiersprache“ keine aussagekräftigen Konzepte sind. Jede Programmiersprache, und ich meine wirklich jede, kann interpretiert oder kompiliert werden. Interpretation und Kompilierung sind also Implementierungstechniken, keine Attribute von Sprachen.

Interpretation ist eine Technik, bei der ein anderes Programm, der Interpreter, Operationen im Namen des zu interpretierenden Programms ausführt, um es auszuführen. Wenn Sie sich vorstellen können, ein Programm zu lesen und Schritt für Schritt das zu tun, was es verspricht, beispielsweise auf einem Stück Rubbelpapier, dann ist es genau das, was ein Dolmetscher auch tut. Ein häufiger Grund für die Interpretation eines Programms ist, dass Dolmetscher relativ einfach zu schreiben sind. Ein weiterer Grund ist, dass ein Interpreter überwachen kann, was ein Programm während der Ausführung versucht, um beispielsweise aus Sicherheitsgründen eine Richtlinie durchzusetzen.

Das Kompilieren ist eine Technik, bei der ein in einer Sprache geschriebenes Programm (die „Ausgangssprache“) in ein Programm in einer anderen Sprache (der „Objektsprache“) übersetzt wird, was hoffentlich dasselbe bedeutet wie das ursprüngliche Programm. Während der Übersetzung versucht der Compiler häufig, das Programm so zu transformieren, dass das Objektprogramm schneller wird (ohne seine Bedeutung zu ändern!). Ein häufiger Grund für das Kompilieren eines Programms ist, dass es eine gute Möglichkeit gibt, Programme in der Objektsprache schnell und ohne den Aufwand für die Interpretation der Ausgangssprache auszuführen.

Sie haben möglicherweise basierend auf den obigen Definitionen vermutet, dass sich diese beiden Implementierungstechniken nicht gegenseitig ausschließen und sich möglicherweise sogar ergänzen. Traditionell war die Objektsprache eines Compilers Maschinencode oder ähnliches, was sich auf eine beliebige Anzahl von Programmiersprachen bezieht, die von bestimmten Computer-CPUs verstanden werden. Der Maschinencode würde dann "auf dem Metall" laufen (obwohl man sehen könnte, wenn man genau hinschaut, dass das "Metall" sehr ähnlich wie ein Interpreter funktioniert). Heutzutage ist es jedoch sehr üblich, einen Compiler zu verwenden, um Objektcode zu generieren, der interpretiert werden soll. So hat beispielsweise Java früher funktioniert (und funktioniert manchmal immer noch). Es gibt Compiler, die andere Sprachen in JavaScript übersetzen, das dann häufig in einem Webbrowser ausgeführt wird, der das JavaScript interpretieren kann. oder kompilieren Sie eine virtuelle Maschine oder nativen Code. Wir haben auch Interpreter für Maschinencode, mit denen eine Art von Hardware auf einer anderen emuliert werden kann. Oder man kann einen Compiler verwenden, um Objektcode zu generieren, der dann der Quellcode für einen anderen Compiler ist, der sogar rechtzeitig im Speicher Code kompiliert, damit er ausgeführt wird, was wiederum der Fall ist. . . Du hast die Idee. Es gibt viele Möglichkeiten, diese Konzepte zu kombinieren.

Bhavin Shah
quelle
Können Sie diesen Satz korrigieren: "Es gibt Compiler, die andere Sprachen in JavaScript übersetzen, das dann häufig in einem Webbrowser ausgeführt wird, der das JavaScript interpretieren oder eine virtuelle Maschine oder nativen Code kompilieren kann."
Koray Tugay
Geschafft. Ein weiterer häufiger Fehler besteht darin, die Nützlichkeit einer Sprache den vorhandenen APIs zuzuschreiben.
Little Endian
10

Der größte Vorteil des interpretierten Quellcodes gegenüber dem kompilierten Quellcode ist die PORTABILITÄT .

Wenn Ihr Quellcode kompiliert ist, müssen Sie für jeden Prozessortyp und / oder jede Plattform, auf der Ihr Programm ausgeführt werden soll, eine andere ausführbare Datei kompilieren (z. B. eine für Windows x86, eine für Windows x64, eine für Linux x64 usw.) auf). Sofern Ihr Code nicht vollständig standardkonform ist und keine plattformspezifischen Funktionen / Bibliotheken verwendet, müssen Sie tatsächlich mehrere Codebasen schreiben und verwalten!

Wenn Ihr Quellcode interpretiert wird, müssen Sie ihn nur einmal schreiben und er kann von einem geeigneten Interpreter auf jeder Plattform interpretiert und ausgeführt werden! Es ist tragbar ! Beachten Sie, dass ein Interpreter selbst ein ausführbares Programm ist , das für eine bestimmte Plattform geschrieben und kompiliert wurde.

Ein Vorteil von kompiliertem Code besteht darin, dass er den Quellcode vor dem Endbenutzer verbirgt (was möglicherweise geistiges Eigentum ist ), da Sie anstelle der Bereitstellung des ursprünglichen, für Menschen lesbaren Quellcodes eine undurchsichtige ausführbare Binärdatei bereitstellen.

Niko Bellic
quelle
1
Unter diesen Bedingungen kann Java nicht als "kompilierte Sprache" betrachtet werden, aber die Kompilierungsphase bietet die Vorteile des Kompilierens (Typprüfung, Früherkennung von Fehlern usw.) und erzeugt Bytecode, der auf jedem Betriebssystem mit Java ausgeführt werden kann virtuelle Maschine zur Verfügung gestellt.
Rogelio Triviño
7

Ein Compiler und ein Interpreter erledigen die gleiche Aufgabe: Sie übersetzen eine Programmiersprache in eine andere Pgoramming-Sprache, die normalerweise näher an der Hardware liegt, und leiten häufig ausführbaren Maschinencode.

Traditionell bedeutet "kompiliert", dass diese Übersetzung auf einmal erfolgt, von einem Entwickler durchgeführt wird und die resultierende ausführbare Datei an Benutzer verteilt wird. Reines Beispiel: C ++. Die Kompilierung dauert normalerweise ziemlich lange und versucht, viele teure Optimierungen vorzunehmen, damit die resultierende ausführbare Datei schneller ausgeführt wird. Endbenutzer verfügen nicht über die Tools und das Wissen, um Inhalte selbst zu kompilieren, und die ausführbare Datei muss häufig auf einer Vielzahl von Hardware ausgeführt werden, sodass Sie nicht viele hardwarespezifische Optimierungen vornehmen können. Während der Entwicklung bedeutet der separate Kompilierungsschritt einen längeren Rückkopplungszyklus.

Traditionell bedeutet "interpretiert", dass die Übersetzung "on the fly" erfolgt, wenn der Benutzer das Programm ausführen möchte. Reines Beispiel: Vanille PHP. Ein naiver Interpreter muss jedes Stück Code bei jeder Ausführung analysieren und übersetzen, was es sehr langsam macht. Es können keine komplexen, kostspieligen Optimierungen durchgeführt werden, da diese länger dauern würden als die bei der Ausführung eingesparte Zeit. Es kann jedoch die Funktionen der Hardware, auf der es ausgeführt wird, voll nutzen. Das Fehlen eines separaten Kompilierungsschritts reduziert die Rückkopplungszeit während der Entwicklung.

Aber heutzutage ist "kompiliert vs. interpretiert" kein Schwarz-Weiß-Thema, dazwischen gibt es Schattierungen. Naive, einfache Dolmetscher sind so gut wie ausgestorben. Viele Sprachen verwenden einen zweistufigen Prozess, bei dem der Code auf hoher Ebene in einen plattformunabhängigen Bytecode übersetzt wird (der viel schneller zu interpretieren ist). Dann haben Sie "Just-in-Time-Compiler", die Code höchstens einmal pro Programmlauf kompilieren, manchmal Ergebnisse zwischenspeichern und sogar intelligent entscheiden, selten ausgeführten Code zu interpretieren und leistungsstarke Optimierungen für häufig ausgeführten Code vorzunehmen. Während der Entwicklung können Debugger den Code innerhalb eines laufenden Programms auch für traditionell kompilierte Sprachen wechseln.

Michael Borgwardt
quelle
1
Das Kompilierungsmodell von C ++ ist jedoch von C geerbt und wurde ohne Berücksichtigung von Funktionen wie Vorlagen entworfen. Diese Unbeholfenheit trägt viel mehr als jeder andere Faktor zu den langen Kompilierungszeiten von C ++ bei - und macht es zu einem schlechten Beispiel.
4

Zunächst einmal ist Java nicht vollständig statisch kompiliert und wie C ++ verknüpft. Es wird in Bytecode kompiliert, der dann von einer JVM interpretiert wird. Die JVM kann eine Just-in-Time-Kompilierung in die native Maschinensprache durchführen, muss dies jedoch nicht.

Mehr auf den Punkt gebracht: Ich denke, Interaktivität ist der wichtigste praktische Unterschied. Da alles interpretiert wird, können Sie einen kleinen Auszug aus Code nehmen, analysieren und gegen den aktuellen Status der Umgebung ausführen. Wenn Sie also bereits Code ausgeführt hätten, der eine Variable initialisiert hat, hätten Sie Zugriff auf diese Variable usw. Es eignet sich wirklich für Dinge wie den Funktionsstil.

Die Interpretation kostet jedoch viel, insbesondere wenn Sie ein großes System mit vielen Referenzen und Kontexten haben. Per Definition ist dies verschwenderisch, da identischer Code möglicherweise zweimal interpretiert und optimiert werden muss (obwohl die meisten Laufzeiten dafür zwischengespeichert und optimiert sind). Trotzdem zahlen Sie Laufzeitkosten und benötigen häufig eine Laufzeitumgebung. Es ist auch weniger wahrscheinlich, dass komplexe interprozedurale Optimierungen auftreten, da deren Leistung derzeit nicht ausreichend interaktiv ist.

Daher ist es für große Systeme, die sich nicht wesentlich ändern werden, und für bestimmte Sprachen sinnvoller, alles vorkompilieren und vorab zu verknüpfen und alle Optimierungen vorzunehmen, die Sie vornehmen können. Dies führt zu einer sehr schlanken Laufzeit, die bereits für den Zielcomputer optimiert ist.

Was das Generieren von Executbles betrifft, hat das meiner Meinung nach wenig damit zu tun. Sie können häufig eine ausführbare Datei aus einer kompilierten Sprache erstellen. Sie können aber auch eine ausführbare Datei aus einer interpretierten Sprache erstellen, mit der Ausnahme, dass der Interpreter und die Laufzeit bereits in der ausführbaren Datei gepackt und vor Ihnen verborgen sind. Dies bedeutet, dass Sie im Allgemeinen immer noch die Laufzeitkosten bezahlen (obwohl ich sicher bin, dass es für einige Sprachen Möglichkeiten gibt, alles in eine ausführbare Baumdatei zu übersetzen).

Ich bin nicht der Meinung, dass alle Sprachen interaktiv gemacht werden könnten. Bestimmte Sprachen wie C sind so stark an die Maschine und die gesamte Linkstruktur gebunden, dass ich nicht sicher bin, ob Sie eine aussagekräftige, vollwertige interaktive Version erstellen können

Uri
quelle
C ist nicht wirklich an eine "Maschine" gebunden. Die Syntax und Semantik von C sind ziemlich einfach. Es sollte nicht besonders schwierig sein, einen C-Interpreter zu implementieren, der nur sehr zeitaufwändig ist (da auch die Standardbibliothek implementiert werden muss). Übrigens kann Java (mit gcj) in nativen Maschinencode kompiliert werden.
Mondhorn
@lunaryorn: Ich bin nicht einverstanden mit GCJ. GCJ bietet Ihnen lediglich eine ausführbare Umgebung. "Kompilierte Anwendungen sind mit der GCJ-Laufzeit libgcj verknüpft, die die Kernklassenbibliotheken, einen Garbage Collector und einen Bytecode-Interpreter
Uri,
2
GCJ tut produzieren nativen Maschinencode, und nicht nur eine ausführbare Umgebung mit eingebetteten Interpreter und Bytecode. libgcj bietet einen Bytecode-Interpreter, der Aufrufe von nativem Code in Java-Bytecode unterstützt und das kompilierte Programm nicht interpretiert. Wenn libgcj keinen Bytecode-Interpreter bereitstellen würde, würde GCJ die Java-Spezifikation nicht erfüllen.
Mondhorn
@lunaryorn: Ah. Ok, ich schätze die Klarstellung und stehe korrigiert. Wir verwenden Java hauptsächlich in einer Windows-Umgebung, daher habe ich gcj seit Jahren nicht mehr ausprobiert.
Uri
2

Es ist ziemlich schwierig, eine praktische Antwort zu geben, da der Unterschied in der Sprachdefinition selbst liegt. Es ist möglich, einen Interpreter für jede kompilierte Sprache zu erstellen, aber es ist nicht möglich, einen Compiler für jede interpretierte Sprache zu erstellen. Es geht sehr um die formale Definition einer Sprache. Damit theoretische Informatik-Sachen, die Noboby an der Universität mag.

Steven Mohr
quelle
1
Sicherlich können Sie einen Compiler für eine interpretierte Sprache erstellen, aber der kompilierte Maschinencode ist selbst ein Spiegel der Laufzeit.
Aiden Bell
2

Das Python-Buch © 2015 Imagine Publishing Ltd unterscheidet den Unterschied einfach durch den folgenden Hinweis, der auf Seite 10 erwähnt wird:

Eine interpretierte Sprache wie Python ist eine Sprache, in der der Quellcode in Maschinencode konvertiert und bei jeder Ausführung des Programms ausgeführt wird. Dies unterscheidet sich von einer kompilierten Sprache wie C, bei der der Quellcode nur einmal in Maschinencode konvertiert wird. Der resultierende Maschinencode wird dann bei jeder Programmausführung ausgeführt.

Ahmed Shaban Helwa
quelle
1

Beim Kompilieren wird ein ausführbares Programm aus Code erstellt, der in einer kompilierten Programmiersprache geschrieben ist. Durch das Kompilieren kann der Computer das Programm ausführen und verstehen, ohne dass die zum Erstellen verwendete Programmiersoftware erforderlich ist. Wenn ein Programm kompiliert wird, wird es häufig für eine bestimmte Plattform (z. B. IBM Plattform) kompiliert, die mit IBM kompatiblen Computern funktioniert, jedoch nicht für andere Plattformen (z. B. Apple Plattform). Der erste Compiler wurde von Grace Hopper während der Arbeit am Harvard Mark I-Computer entwickelt. Heutzutage enthalten die meisten Hochsprachen einen eigenen Compiler oder Toolkits, mit denen das Programm kompiliert werden kann. Ein gutes Beispiel für einen mit Java verwendeten Compiler ist Eclipse, und ein Beispiel für einen mit C und C ++ verwendeten Compiler ist der Befehl gcc.

salehvm
quelle
0

Kurze (ungenaue) Definition:

Kompilierte Sprache: Das gesamte Programm wird sofort in Maschinencode übersetzt, dann wird der Maschinencode von der CPU ausgeführt.

Interpretierte Sprache: Das Programm wird zeilenweise gelesen, und sobald eine Zeile gelesen wird, werden die Maschinenanweisungen für diese Zeile von der CPU ausgeführt.

Aber wirklich, heutzutage werden nur wenige Sprachen rein kompiliert oder interpretiert, es ist oft eine Mischung. Eine detailliertere Beschreibung mit Bildern finden Sie in diesem Thread:

Was ist der Unterschied zwischen Zusammenstellung und Interpretation?

Oder mein späterer Blogbeitrag:

https://orangejuiceliberationfront.com/the-difference-between-compiler-and-interpreter/

uliwitness
quelle