Warum benötigt die C-Programmierung einen Compiler und Shell-Skripte nicht?

8

Ich habe ein Bash-Skript geschrieben und es ausgeführt, ohne es zuerst zu kompilieren. Es hat perfekt funktioniert. Es kann mit oder ohne Berechtigungen funktionieren, aber wenn es um C-Programme geht, müssen wir den Quellcode kompilieren. Warum?

Mischling
quelle
9
Dies bedeutet, dass C eine kompilierte Sprache und Bash eine interpretierte Sprache ist. Nicht mehr, nicht weniger.
Radon Rosborough
10
Ich stimme dafür, diese Frage als nicht zum Thema gehörend zu schließen, da sie nicht mit U & L zusammenhängt, und selbst wenn dies der Fall wäre, ist sie zu weit gefasst, da man sie endlos diskutieren kann, ohne eine zufriedenstellende Antwort zu geben, ohne von einer Antwort zu sprechen, die zum passt allgemeine Vorstellung davon, dass U & L eine Wissensbasis zur Lösung von Problemen ist.
Gegenmodus
4
@countermode Sie stapeln (Austausch | Überlauf) Leute und und Ihre triggerfreudigen Close-Votes. Die Frage ist nicht weit gefasst: Sie enthüllt ein sehr spezifisches fehlendes Verständnis: den Unterschied zwischen kompilierten und interpretierten Sprachen. Dies erfordert ein paar Absätze, um zu erklären, und ein paar weitere Absätze, um die (Nachteile) jedes einzelnen aufzuzeigen, sowie eine Fußnote, um zusammenzufassen, dass C und Bash unterschiedliche Ziele hatten, und sie wählten daher die unterschiedlichen Ansätze.
mtraceur
2
@mtraceur Sorry, ich will niemanden beleidigen. Ab Trigger-Happy-Close-Votes ist dies etwas unfair. Fünf Stimmen sind erforderlich, um eine Frage zu schließen, und wenn jemand anderes dafür stimmt, sie nicht zu schließen, bin ich damit einverstanden. Sie haben absolut Recht mit der Frage, aber ich bin mir nicht sicher, ob solche Fragen laut unix.stackexchange.com/help/on-topic zu U & L gehören .
Gegenmodus
2
@mtraceur Wenn Sie denken, dass es nicht breit ist, stimme ich Ihnen nicht zu. Es gibt viel zu erzählen über den Unterschied zwischen Compiler / Interpreter / etc. und interpretierte / kompilierte Sprachen. Es gibt Caevats, die leicht zu treffen sind. Darüber hinaus passt die Frage besser zu "Computer Science" oder "Programmers" SE.
Matthew Rock

Antworten:

23

Dies bedeutet, dass Shell-Skripte nicht kompiliert, sondern interpretiert werden: Die Shell interpretiert Skripte Befehl für Befehl und findet jedes Mal heraus, wie die einzelnen Befehle ausgeführt werden. Dies ist für Shell-Skripte sinnvoll, da sie ohnehin die meiste Zeit damit verbringen, andere Programme auszuführen.

C-Programme hingegen werden normalerweise kompiliert: Bevor sie ausgeführt werden können, konvertiert ein Compiler sie ein für alle Mal in Maschinencode. In der Vergangenheit gab es C-Dolmetscher (wie den C-Interpreter von HiSoft auf dem Atari ST), aber sie waren sehr ungewöhnlich. Heutzutage sind C-Compiler sehr schnell; TCC ist so schnell, dass Sie damit "C-Skripte" mit einem #!/usr/bin/tcc -runShebang erstellen können , sodass Sie C-Programme erstellen können , die auf die gleiche Weise wie Shell-Skripte ausgeführt werden (aus Sicht der Benutzer).

Einige Sprachen haben normalerweise sowohl einen Interpreter als auch einen Compiler: BASIC ist ein Beispiel, das mir in den Sinn kommt.

Sie können auch sogenannte Shell-Skript-Compiler finden, aber die, die ich gesehen habe, sind nur verschleierte Wrapper: Sie verwenden immer noch eine Shell, um das Skript tatsächlich zu interpretieren. Wie mtraceur betont , wäre ein richtiger Shell-Skript-Compiler sicherlich möglich, aber nicht sehr interessant.

Eine andere Möglichkeit, darüber nachzudenken, besteht darin, zu berücksichtigen, dass die Skriptinterpretationsfunktion einer Shell eine Erweiterung ihrer Befehlszeilenverarbeitungsfunktion darstellt, was natürlich zu einem interpretierten Ansatz führt. C hingegen wurde entwickelt, um eigenständige Binärdateien zu erstellen. Dies führt zu einem kompilierten Ansatz. Sprachen, die normalerweise kompiliert werden, neigen dazu, auch Interpreter oder zumindest Befehlszeilen-Parser zu sprießen (bekannt als REPLs, Read-Eval-Print-Schleifen ; eine Shell ist selbst eine REPL).

Stephen Kitt
quelle
1
Viele "Compiler" für Skriptsprachen sind nur Wrapper. Ich erinnere mich an einen BASIC-Compiler, der die ausführbare Interpreter-Datei nur mit einem komprimierten Quellcode verkettet.
Dmitry Grigoryev
@DmitryGrigoryev Das kann ich leicht glauben! Für BASIC habe ich an Compiler wie Turbo Basic gedacht. Ich denke, es gab einige echte Compiler für DOS-BAT-Dateien, aber ich könnte mich irren! Es gibt auch den üblichen P-Code-Ansatz ...
Stephen Kitt
1
Beachten Sie, dass ein "wahrer" Compiler für die Shell durchaus möglich ist. Es ist einfach nicht der Regel lohnt sich der Aufwand / Komplexität, da eine naive Variante würde nur ein Programm produzieren , dass im Allgemeinen ein Bündel nennt execve, open, close, read, write, und pipesyscalls, durchsetzt mit einigen getenv, setenvund interne hashmap / Array - Operationen (für Nicht-exportierten Variablen ), etc. Bourne Shell und Derivate sind auch keine Programmiersprachen, die so viel von Low-Level-Compiler-Optimierungen wie Code-Neuordnung usw.
profitieren
@StephenKitt würde es Ihnen etwas ausmachen, wenn ich eine neue Frage zu einem Kommentar Ihrer Antwort stelle. Obwohl Sie antworten, erklärt viel. wirft aber auch eine neue Frage für mich auf.
Mischling
Natürlich würde ich eine neue Frage stellen. Ich dachte, Sie möchten vielleicht, dass ich es im Chat frage. weil es sich auf Ihre Antwort bezieht.
Mischling
6

Betrachten Sie das folgende Programm:

2 Mars Bars
2 Milks
1 Bread
1 Corn Flakes

Auf dem bashWeg wandern Sie durch den Laden und suchen nach Marsbars, suchen sie schließlich und suchen dann nach Milch usw. Dies funktioniert, weil Sie ein komplexes Programm namens "Erfahrener Käufer" ausführen, das ein Brot erkennt, wenn Sie eines sehen und all die anderen Komplexitäten des Einkaufens. bashist ein ziemlich komplexes Programm.

Alternativ können Sie Ihre Einkaufsliste einem Einkaufs-Compiler übergeben. Der Compiler denkt eine Weile nach und gibt Ihnen eine neue Liste. Diese Liste ist LANG , besteht aber aus viel einfacheren Anweisungen:

... lots of instructions on how to get to the store, get a shopping cart etc.
move west one aisle.
move north two sections.
move hand to shelf three.
grab object.
move hand to shopping cart.
release object.
... and so on and so forth.

Wie Sie sehen können, weiß der Compiler genau, wo sich alles im Shop befindet, sodass die gesamte Phase "Nach Dingen suchen" nicht benötigt wird.

Dies ist ein eigenständiges Programm, für dessen Ausführung kein "erfahrener Käufer" erforderlich ist. Alles was es braucht ist ein Mensch mit "Basic Human Operating System".

Zurück zu Computerprogrammen: bashist "Erfahrener Käufer" und kann ein Skript nehmen und es einfach tun, ohne etwas zu kompilieren. Der AC-Compiler erstellt ein eigenständiges Programm, für dessen Ausführung keine Hilfe mehr erforderlich ist.

Sowohl Interpreter als auch Compiler haben ihre Vor- und Nachteile.

Stig Hemmer
quelle
3
Schöne Analogie ... erklärt auch, warum Sie dieselbe Einkaufsliste, aber nicht denselben Maschinencode auf einer anderen Architektur verwenden können (sic!) - alles befindet sich an verschiedenen Orten usw. Möglicherweise benötigen Sie jedoch einen anderen "erfahrenen Käufer" Wer kennt die verschiedenen Supermärkte.
Peter - Monica
6

Es kommt alles auf den technischen Unterschied an, wie das Programm, das Sie als Mensch lesen / schreiben können, in die Maschinenanweisungen konvertiert wird, die Ihr Computer versteht - und die unterschiedlichen Vor- und Nachteile jeder Methode sind der Grund, warum einige Sprachen so geschrieben werden, dass sie Compiler benötigen und einige sind geschrieben, um interpretiert zu werden.

Erstens der technische Unterschied

(Hinweis: Ich vereinfache hier viel, um die Frage zu beantworten. Für ein tieferes Verständnis erläutern / verfeinern die technischen Hinweise am Ende meiner Antwort einige der Vereinfachungen hier und die Kommentare zu dieser Antwort einige nützliche Klarstellungen und Diskussionen auch ..)

Grundsätzlich gibt es zwei allgemeine Kategorien von Programmiersprachen:

  1. Ein anderes Programm (der "Compiler") liest Ihr Programm, bestimmt, welche Schritte Ihr Code ausführen soll, und schreibt dann ein neues Programm in Maschinencode (die "Sprache", die Ihr Computer selbst versteht), die diese Schritte ausführt .
  2. Ein anderes Programm (der "Interpreter") liest Ihr Programm, bestimmt, welche Schritte Ihr Code vorschreibt, und führt diese Schritte dann selbst aus . Es wird kein neues Programm erstellt.

C gehört zur ersten Kategorie (der C- Compiler übersetzt die C- Sprache in den Maschinencode Ihres Computers : Der Maschinencode wird in einer Datei gespeichert, und wenn Sie diesen Maschinencode ausführen, macht er, was Sie wollen).

Bash gehört zur zweiten Kategorie (der Bash- Interpreter liest die Bash- Sprache und der Bash- Interpreter macht das, was Sie wollen: Es gibt also kein "Compilermodul" an sich, der Interpreter interpretiert und führt aus, während ein Compiler liest und übersetzt). .

Möglicherweise haben Sie bereits bemerkt, was dies bedeutet:

Mit C führen Sie den Schritt "Interpretieren" einmal aus . Wenn Sie das Programm ausführen müssen, weisen Sie Ihren Computer an, den Maschinencode auszuführen. Ihr Computer kann ihn einfach direkt ausführen, ohne zusätzliche "Überlegungen" anstellen zu müssen.

Mit bash müssen Sie jedes Mal, wenn Sie das Programm ausführen, den Schritt "Interpretieren" ausführen - auf Ihrem Computer wird der Bash-Interpreter ausgeführt, und der Bash-Interpreter führt jedes Mal zusätzliche "Überlegungen" durch, um herauszufinden, was für jeden Befehl zu tun ist .

Daher benötigen C-Programme mehr CPU, Speicher und Zeit für die Vorbereitung (Kompilierungsschritt), aber weniger Zeit und Arbeit für die Ausführung. Bash-Programme benötigen weniger CPU, Speicher und Zeit für die Vorbereitung, aber mehr Zeit und Arbeit für die Ausführung. Sie werden diese Unterschiede wahrscheinlich die meiste Zeit nicht bemerken, weil Computer heutzutage sehr schnell sind, aber es macht einen Unterschied, und dieser Unterschied summiert sich, wenn Sie große oder komplizierte Programme oder viele kleine Programme ausführen müssen.

Da C-Programme in Maschinencode (die "Muttersprache") des Computers konvertiert werden, können Sie ein Programm nicht auf einen anderen Computer mit einem anderen Maschinencode kopieren (z. B. Intel 64-Bit auf Intel 32) -bit oder von Intel zu ARM oder MIPS oder was auch immer). Sie haben die Zeit zu verbringen , es für die andere Maschinensprache zu kompilieren wieder . Ein Bash-Programm kann jedoch einfach auf einen anderen Computer verschoben werden, auf dem der Bash-Interpreter installiert ist, und es läuft einwandfrei.

Nun zum Warum Teil Ihrer Frage

Die Hersteller von C haben vor einigen Jahrzehnten ein Betriebssystem und andere Programme auf Hardware geschrieben, das durch moderne Standards eher eingeschränkt war. Aus verschiedenen Gründen war die Konvertierung der Programme in den Maschinencode des Computers zu dieser Zeit der beste Weg, um dieses Ziel zu erreichen. Außerdem erledigten sie die Art von Arbeit, bei der es wichtig war, dass der von ihnen geschriebene Code effizient lief .

Und die Macher der Bourne-Shell und -Bash wollten das Gegenteil: Sie wollten Programme / Befehle schreiben, die sofort ausgeführt werden konnten - in der Befehlszeile eines Terminals möchten Sie nur eine Zeile, einen Befehl schreiben und haben ausführen. Und sie wollten, dass Skripte, die Sie geschrieben haben, überall dort funktionieren, wo Sie den Shell-Interpreter / das Shell-Programm installiert haben.

Fazit

Kurz gesagt, Sie benötigen keinen Compiler für Bash, aber einen für C, da diese Sprachen unterschiedlich in tatsächliche Computeraktionen konvertiert werden und diese unterschiedliche Vorgehensweise ausgewählt wurde, weil die Sprachen unterschiedliche Ziele hatten.

Sonstige technische / erweiterte Details / Hinweise

  1. Sie könnten tatsächlich einen C- Interpreter oder einen Bash- Compiler erstellen. Nichts hindert das daran, möglich zu sein: Es sind nur diese Sprachen, die für verschiedene Zwecke entwickelt wurden. Es ist oft einfacher, das Programm einfach in eine andere Sprache umzuschreiben, als einen guten Interpreter oder Compiler für eine komplexe Programmiersprache zu schreiben. Besonders wenn diese Sprachen eine bestimmte Sache haben, in der sie gut waren und in erster Linie mit einer bestimmten Arbeitsweise entworfen wurden. C wurde für die Kompilierung entwickelt, daher fehlt eine Menge praktischer Kurzform, die Sie in einer interaktiven Shell benötigen, aber es ist sehr gut geeignet, um eine sehr spezifische Manipulation von Daten / Speicher auf niedriger Ebene und die Interaktion mit dem Betriebssystem auszudrücken Dies sind Aufgaben, die Sie häufig ausführen, wenn Sie effizient kompilierten Code schreiben möchten. In der Zwischenzeit ist bash sehr gut darin, andere Programme auszuführen.

  2. Weiterführende Details: Es gibt tatsächlich Programmiersprachen, die eine Mischung aus beiden Typen sind (sie übersetzen den Quellcode "meistens", so dass sie den größten Teil der Interpretation / des "Denkens" einmal und nur wenig tun können der Interpretation / "Denken" später). Java, Python und viele andere moderne Sprachen sind tatsächlich solche Mischungen: Sie versuchen, Ihnen einige der Portabilitäts- und / oder Entwicklungsvorteile der interpretierten Sprachen und einige der Geschwindigkeit kompilierter Sprachen zu vermitteln. Es gibt viele Möglichkeiten, solche Ansätze zu kombinieren, und verschiedene Sprachen tun dies unterschiedlich. Wenn Sie sich mit diesem Thema befassen möchten, können Sie sich über Programmiersprachen informieren, die in "Bytecode" kompiliert werden (ähnlich wie das Kompilieren in Ihre eigene erfundene "Maschinensprache").

  3. Sie haben nach dem Ausführungsbit gefragt: Tatsächlich ist das ausführbare Bit nur dazu da, dem Betriebssystem mitzuteilen, dass diese Datei ausgeführt werden darf . Ich vermute, dass der einzige Grund, warum Bash-Skripte ohne die Ausführungsberechtigung für Sie funktionieren , darin besteht, dass Sie sie in einer Bash-Shell ausführen . Normalerweise gibt das Betriebssystem nur einen Fehler zurück, wenn es aufgefordert wird, eine Datei ohne gesetztes Ausführungsbit auszuführen. Einige Shells wie bash werden diesen Fehler jedoch erkennen und es sich zur Aufgabe machen, die Datei trotzdem auszuführen, indem sie im Grunde die Schritte emulieren, die das Betriebssystem normalerweise ausführen würde (lesen Sie die Zeile "#!" Am Anfang der Datei und versuchen Sie es um dieses Programm auszuführen, um die Datei zu interpretieren, mit einer Standardeinstellung von entweder selbst oder /bin/shwenn es keine "#!" - Zeile gibt).

  4. Manchmal ist bereits ein Compiler auf Ihrem System installiert, und manchmal werden IDEs mit einem eigenen Compiler geliefert und / oder führen die Kompilierung für Sie aus. Dadurch fühlt sich eine kompilierte Sprache möglicherweise wie eine nicht kompilierte Sprache an, aber der technische Unterschied ist immer noch vorhanden.

  5. Eine "kompilierte" Sprache wird nicht unbedingt in Maschinencode kompiliert, und das gesamte Kompilieren ist ein Thema für sich. Grundsätzlich wird der Begriff weit verbreitet verwendet: Er kann sich tatsächlich auf einige Dinge beziehen. In einem bestimmten Sinne ist ein "Compiler" nur ein Übersetzer von einer Sprache (normalerweise eine "höhere" Sprache, die für Menschen einfacher zu verwenden ist) in eine andere Sprache (normalerweise eine "niedrigere" Sprache, die für Computer einfacher zu verwenden ist - manchmal, aber eigentlich nicht sehr oft, ist dies Maschinencode). Manchmal, wenn Leute "Compiler" sagen, sprechen sie wirklich davon, dass mehrere Programme zusammenarbeiten (für einen typischen C-Compiler sind es tatsächlich vier Programme: der "Pre-Prozessor", der Compiler selbst, der "Assembler" und der " Linker ").

mtraceur
quelle
Ich verstehe nicht, warum diese Frage abgelehnt wurde. Es ist eine beeindruckend umfassende Antwort auf eine Frage, die breit und nicht sehr klar ist.
Anthony Geoghegan
Der Compiler übersetzt eine Sprache in eine andere. Es muss nicht in Maschinensprache kompiliert werden. Sie können Bytecode-Compiler haben. Java-zu-ASM-Compiler usw. Die Hersteller von C wollten nicht die meiste Leistung, sondern die Sprache, die ihren Anforderungen entspricht. C könnte bis zu einem gewissen Grad interpretiert werden. Bash könnte kompiliert werden - es gibt shc . Ob die Sprache meistens kompiliert / interpretiert wird oder nicht, hängt von den von Ihnen verwendeten Tools ab, nicht von der Sprache selbst, obwohl einige Konventionen befolgt werden.
Matthew Rock
@MatthewRock Ich habe einen technischen Hinweis hinzugefügt, um das Kompilieren in nicht unbedingt maschinensprachliche Dinge zu behandeln. Ich habe das Gefühl, dass meine erste technische Anmerkung bereits die Sache "C könnte interpretiert werden ... Bash könnte kompiliert werden" abdeckt. Ich habe eine Idee, wie man das Problem "Die Macher von C wollten nicht die meiste Leistung" angehen kann, obwohl ich denke, dass es ziemlich klar ist, dass sie die Sprache so gestaltet haben, dass sie auf der Hardware, die sie zu der Zeit verwendeten, effizient ist (das Null-Byte- Die Sache mit dem As-String-Terminator war zum Teil darauf zurückzuführen, dass Sie auf diese Weise ein Register weniger verwenden konnten, wenn Sie einen String auf diesen durchlaufen.
mtraceur
@MatthewRock (Forts.) Ich denke, es ist fair zu sagen, dass die Macher von C nicht gerade Leistung wollten, aber sie wollten die Arbeit zum Schreiben von Betriebssystemen abstrahieren, was besonders in jenen Tagen etwas war, in dem Codeeffizienz wertvoll war. Und es war Arbeit, die sie sonst im Assembler erledigt hätten. So erstellten sie eine Sprache, die eng mit dem Maschinencode korrelierte, der von den PDP-Maschinen verwendet wurde, für die sie ihren Code schrieben, was sich zumindest als Nebeneffekt, wenn nicht als bemerkenswertes Entwurfsziel, für die Effizienz auf dieser Plattform anbot. auch mit naiven nicht optimierenden Compilern.
mtraceur
Sie würden es nicht im Assembler tun. Sie hatten B . Überall Fallstricke, und Fragen sind hier nicht zum Thema. Insgesamt würde die Antwort wahrscheinlich die Frage beantworten, aber es gibt immer noch Details, die nicht korrekt sind.
Matthew Rock
5

Programmier- / Skriptsprachen können kompiliert oder interpretiert werden.

Kompilierte ausführbare Dateien sind immer schneller und viele Fehler können vor der Ausführung erkannt werden.

Interpretierte Sprachen sind in der Regel einfacher zu schreiben und anzupassen, da sie weniger streng sind als kompilierte Sprachen. Sie müssen nicht kompiliert werden, wodurch sie einfacher zu verteilen sind.

Julie Pelletier
quelle
1
Im Bash-Skript gibt es auch einen Fehler, wenn es ausgeführt wird. aber wir kompilieren es nicht.
Mischling
30
ist immer ein gefährliches Wort…
Radon Rosborough
3
Optimiertes kompiliertes CPython ist häufig langsamer als optimiertes asm.js (eine Teilmenge von JavaScript). Daher gibt es ein Beispiel dafür, dass es nicht schneller ist und daher nicht "immer" schneller. Es ist jedoch normalerweise viel, viel schneller.
wizzwizz4
2
Dies beantwortet die Frage nicht.
Mathreadler
3
Immer schneller ist eine kühne Behauptung. Dies geht jedoch zu tief in die Compiler- und Interpreter-Theorie (und Definition) ein.
Giacomo Catenazzi
3

Stellen Sie sich vor, dass Englisch nicht Ihre Muttersprache ist (das könnte für Sie recht einfach sein, wenn Englisch nicht Ihre Muttersprache ist).

Es gibt drei Möglichkeiten, wie Sie dies lesen können:

  1. (Interpretiert) Übersetzen Sie beim Lesen jedes Wort jedes Mal, wenn Sie es sehen
  2. (Optimiert-Interpretiert) Finden Sie gebräuchliche Phrasen (wie "Ihre Muttersprache"), übersetzen Sie sie und schreiben Sie sie auf. Übersetzen Sie dann jedes Wort - mit Ausnahme der Sätze, die Sie bereits übersetzt haben
  3. (Zusammengestellt) Bitten Sie jemanden, die gesamte Antwort zu übersetzen

Computer haben eine Art "Muttersprache" - eine Kombination aus Anweisungen, die der Prozessor versteht, und Anweisungen, die das Betriebssystem (z. B. Windows, Linux, OSX usw.) versteht. Diese Sprache ist für Menschen nicht lesbar.

Skriptsprachen wie Bash fallen normalerweise in die Kategorien 1 und 2. Sie nehmen jeweils eine Zeile, übersetzen diese Zeile und führen sie aus. Fahren Sie dann mit der nächsten Zeile fort. Unter Mac und Linux werden standardmäßig einige verschiedene Interpreter für verschiedene Sprachen wie Bash, Python und Perl installiert. Unter Windows müssen Sie diese selbst installieren.

Viele Skriptsprachen führen eine kleine Vorverarbeitung durch. Versuchen Sie, die Ausführung zu beschleunigen, indem Sie Codestücke kompilieren, die häufig ausgeführt werden oder die Anwendung sonst verlangsamen würden. Einige Begriffe, von denen Sie vielleicht hören, umfassen die AOT-Kompilierung (Ahead-of-Time) oder die JIT-Kompilierung (Just-in-Time).

Schließlich übersetzen kompilierte Sprachen - wie C - das gesamte Programm, bevor Sie sie ausführen können. Dies hat den Vorteil, dass die Übersetzung auf einem anderen Computer als der Ausführung durchgeführt werden kann. Wenn Sie also dem Benutzer das Programm geben, obwohl möglicherweise noch Fehler vorliegen, können bereits verschiedene Arten von Fehlern behoben werden. Genau wie wenn Sie dies Ihrem Übersetzer gegeben haben und ich erwähne, wie das garboola mizene resplunksfür Sie wie gültiges Englisch aussehen könnte, aber der Übersetzer kann Ihnen sagen, dass ich Unsinn spreche. Wenn Sie ein kompiliertes Programm ausführen, benötigt es keinen Interpreter - es ist bereits in der Muttersprache des Computers

Kompilierte Sprachen haben jedoch einen Nachteil: Ich erwähnte, dass Computer eine Muttersprache haben, die sich aus Funktionen der Hardware und des Betriebssystems zusammensetzt. Wenn Sie Ihr Programm unter Windows kompilieren, erwarten Sie nicht, dass das kompilierte Programm ausgeführt wird ein Mac. Einige Sprachen umgehen dies, indem sie zu einer Art Halbsprache kompilieren - ein bisschen wie Pidgin English -. Auf diese Weise erhalten Sie die Vorteile einer kompilierten Sprache sowie eine kleine Geschwindigkeitssteigerung, aber dies bedeutet, dass Sie bündeln müssen einen Interpreter mit Ihrem Code (oder verwenden Sie einen bereits installierten).

Schließlich hat Ihre IDE wahrscheinlich Ihre Dateien für Sie kompiliert und konnte Sie über Fehler informieren, bevor Sie den Code ausgeführt haben. Manchmal kann diese Fehlerprüfung ausführlicher sein als der Compiler. Ein Compiler prüft oft nur so viel, wie er benötigt, um vernünftigen nativen Code zu erzeugen. Eine IDE führt häufig einige zusätzliche Überprüfungen durch und kann Ihnen beispielsweise mitteilen, ob Sie eine Variable zweimal definiert haben oder ob Sie etwas importiert haben, das Sie nicht verwendet haben.

user208769
quelle
Diese Antwort ist großartig, aber ich denke, die dynamische Kompilierung, die vom Perl- "Interpreter" verwendet wird, unterscheidet sich von dem, was normalerweise als "JIT" bezeichnet wird. Daher ist es wahrscheinlich am besten, diesen Begriff zu vermeiden. JIT wird üblicherweise verwendet, um auf die Just-in-Time-Kompilierung von einem bereits kompilierten Bytecode zum Zielcomputercode zu verweisen , z. B. JVM, .Net CLR.
IMSoP
@IMSoP Ja, Sprachen, die bytekompiliert werden, und Sprachen, die JIT aus Bytecode kompiliert, sind in der Tat verschiedene Dinge. Ich denke, es könnte erwähnenswert sein (ich habe einen kurzen Verweis darauf in den Fußnoten meiner Antwort eingefügt), aber die allgemeine Idee, in die JIT fällt, die ich für wertvoll halte, ist, dass es möglich ist, irgendwo zwischen "kompiliert" zu liegen. und "interpretiert", dh teilweise kompiliert und teilweise interpretiert. Trotzdem bin ich mir nicht sicher, ob dies für jemanden, der die Unterscheidung zwischen kompiliert / interpretiert wie dem OP noch nicht versteht, wertvoller oder verwirrender / ablenkender ist.
mtraceur
@mtraceur Um ehrlich zu sein, verliere ich mich sogar ein bisschen in der Unterscheidung zwischen den Modellen von beispielsweise PHP 7, Perl 5, .Net und Java. Die vielleicht beste Zusammenfassung für einen Anfänger ist "es gibt verschiedene Möglichkeiten, Kompilierung und Interpretation zu mischen, einschließlich der Verwendung einer Zwischendarstellung und des Kompilierens oder Neukompilierens von Blöcken, während das Programm ausgeführt wird".
IMSoP
@IMSoP Ich stimme zu. Das ist irgendwie der Ansatz, den ich in meiner Antwort gewählt habe, und dieser Kommentar von Ihnen gab mir eine Idee, wie ich das weiter verfeinern kann. Also vielen Dank.
mtraceur
@IMSoP JIT tritt nicht nur bei Bytecode auf - beispielsweise verfügt node.js über einige JIT-Funktionen. Aber ich stimme zu - ich habe sie alle der Einfachheit halber unter dem Banner "JIT" zusammengefasst, da dies sich wie eine Anfängerfrage anfühlte - ich bearbeite sie, um einen einfacheren Begriff zu verwenden.
user208769
1

Viele Leute sprechen von Interpretation vs. Kompilierung, aber ich denke, dies kann etwas irreführend sein, wenn man es sich genau ansieht, da einige interpretierte Sprachen vor der Ausführung tatsächlich zu einem Zwischenbytecode kompiliert werden.

Der eigentliche Grund, warum C-Programme in ein ausführbares Format kompiliert werden müssen, besteht darin, dass der Computer viel Arbeit leisten muss, um den Code in einer C-Quelldatei in etwas umzuwandeln, das ausgeführt werden kann, sodass es sinnvoll ist, das Produkt zu speichern von all dem funktioniert in einer ausführbaren Datei, so dass Sie es nicht jedes Mal wiederholen müssen, wenn Sie Ihr Programm ausführen möchten.

Andererseits muss der Shell-Interpreter nur sehr wenig Arbeit leisten, um ein Shell-Skript in "Maschinenoperationen" zu konvertieren. Grundsätzlich muss das Skript nur zeilenweise gelesen, in Leerzeichen aufgeteilt, einige Dateiumleitungen und Pipelines eingerichtet und anschließend ein Fork + Exec ausgeführt werden. Da der Aufwand für das Parsen und Verarbeiten der Texteingabe eines Shell-Skripts im Vergleich zu der Zeit, die zum Starten der Prozesse im Shell-Skript benötigt wird, sehr gering ist, wäre es übertrieben, die Shell-Skripte in ein Zwischen-Maschinenformat zu kompilieren, anstatt nur zu interpretieren den Quellcode direkt.

Hugomg
quelle
+1, obwohl ich mich frage, ob dies nicht "den Karren vor das Pferd stellen" ist: Vielleicht sollten die Originalschalen ursprünglich interaktiv verwendet werden können und daher so wenig Aufwand verursachen, dass sie sich nicht um das Kompilieren kümmern, und die relative Einfachheit war Nur eine darauf basierende Designentscheidung?
mtraceur
Ja, das ist eine andere Art, diese Frage zu betrachten :)
Hugomg