Was hindert C daran, kompiliert / interpretiert / JIT'ed zu werden?

9

Java wird oft für seine erstaunliche Portabilität gelobt, die vermutlich auf die JVM zurückzuführen ist. Meine Frage ist, was verhindert, dass C kompiliert / interpretiert / JIT'ed wird. Wenn ja, kann C auch einmal geschrieben werden und auf jedem Gerät funktionieren, das Sie haben. Dies ist jedoch kein beliebter Mechanismus zur Verarbeitung eines C-Programms.

Was sind die Nachteile der Verarbeitung von C auf diese Weise, und was sind die Vorteile der Verarbeitung von Java auf diese Weise und der Nichtkompilierung in Maschinencode, abgesehen von der Portabilität natürlich?

SphericalCow
quelle
Ihre Frage hat hier bereits einige sehr gute Antworten: stackoverflow.com/questions/3925947/…
Doc Brown
2
@delnan Mein Punkt ist, dass "was C davon abhält, kompiliert / interpretiert / JIT'ed zu werden" wirklich seine Bedeutung verliert, wenn die Sprache auf eine virtuelle Maschine mit JIT abzielt oder Situationen, in denen die VM fehlende Funktionen in der Hardware identifiziert und die neu kompiliert Code, der mit der vorhandenen Hardware übereinstimmt (z. B. mit OpenGL (in C geschrieben) unter OSX für verschiedene Grafikkarten). Nein, Sie können auf einem Computer nicht etwas kompilieren, das für llvm als Ziel kompiliert wurde, und es als solches auf einem anderen Prozessor ausführen. Die kompilierte / interpretierte / JIT-Zeile kann jedoch ziemlich unscharf sein.
1
Java wird oft gehypt für seine erstaunliche Beweglichkeit. Es ist portabel auf Systeme, auf denen die JVM kompiliert wurde, dh auf Systeme, für die die JVM (in C geschrieben) kompiliert wurde. Nichts hindert daran, C-Code auf die gleiche Weise zu behandeln, außer dass niemand genug Nutzen daraus zieht, um den Aufwand zu rechtfertigen.
Pete Becker
2
Ich bin verwirrt über dieses Bit: "Was verhindert, dass C kompiliert wird / [...]". Äh, nichts?
Andres F.
1
C-Compiler sind heutzutage ziemlich schnell, daher wird "make myprog.c; myprog" wahrscheinlich schneller ausgeführt als die meisten Interpreter.
James Anderson

Antworten:

18

C ist das, was ich als Mittelsprache bezeichnen würde. Sein Zweck ist es, als "Assembler auf sehr hoher Ebene" zu dienen, weshalb es so gut als Compiler-Ziel funktioniert und die Portabilität so gut unterstützt.

In der Vergangenheit wurden Dolmetscher normalerweise im Zusammenhang mit Methodenaufrufen mit Hochsprachen verwendet . In seiner einfachsten Form analysiert ein Interpreter lediglich jedes Schlüsselwort in der Ausgangssprache zusammen mit den zugehörigen Token und konvertiert diese in Methodenaufrufe und Parameter. In der Praxis konvertieren die meisten Dolmetscher die Ausgangssprache in eine Zwischendarstellung, und diese Darstellung wird interpretiert.

Was hindert C daran, interpretiert oder Jitted zu werden? Nichts. Aber das ist nicht Cs Daseinsberechtigung.

Robert Harvey
quelle
6

Zunächst ist anzumerken, dass Suns JVM in C geschrieben wurde. C ist eine sehr beliebte Sprache, wenn Portabilität erforderlich ist.

Die C- Sprache ist portabel, obwohl dies bei vielen C- Programmen nicht der Fall ist. Dies liegt daran, dass C dem Programmierer nicht so viele Einschränkungen auferlegt oder so viele Annahmen trifft. Wenn ein C-Programmierer möchte, dass seine Programme portabel sind, muss er sich diese Einschränkungen auferlegen.

In der Praxis ist das wirklich nicht viel schwieriger, als mit den Einschränkungen zu leben, die Java Ihnen auferlegt. Es geht hauptsächlich darum, Ihre Endianness und primitiven Größen zu berücksichtigen und tragbare Bibliotheken wie GTK + anstelle plattformspezifischer Bibliotheken zu verwenden.

Sie könnten ein GTK + -Ziel und einen C-Compiler erstellen, die eine virtuelle Maschine unterstützen, wahrscheinlich sogar die JVM, und vorhandenen Code mit sehr wenigen Änderungen zum Laufen bringen. In der Tat wäre eine virtuelle C-Maschine ohne die Garbage Collection wahrscheinlich viel einfacher. Warum willst du das aber?

Das Umgekehrte, Java in nativen Code zu kompilieren, ist ebenfalls möglich. Genau das macht die JIT. Warum willst du das aber? Ich bin mir sicher, dass es Haustierprojekte gibt, die dies "nur weil" tun, aber sie werden nicht ernsthaft verwendet.

Karl Bielefeldt
quelle
5

Du sagtest:

Java wird oft für seine erstaunliche Portabilität gelobt, die vermutlich auf die JVM zurückzuführen ist.

Und da, im ersten Satz, liegen Sie falsch. Java ist aufgrund der JVM nicht portierbar. Java ist portabel, da die Java-Sprache so definiert ist, dass der Implementierer keinen Spielraum für das Verhalten eines Programms hat.

Java hat beispielsweise zwei Typen: "int" (vorzeichenbehaftete 32-Bit-Ganzzahl) und "long" (vorzeichenbehaftete 64-Bit-Ganzzahl). C und C ++ haben "int" (mindestens 16 Bit signiert), "long" (mindestens 32 Bit signiert) und "long long" (mindestens 64 Bit signiert). Das liegt daran, dass C auf vielen verschiedenen Prozessoren ausgeführt werden soll und es ihnen ermöglicht, sich unterschiedlich zu verhalten.

C könnte feste Größen für diese Typen definiert haben. Wenn dies der Fall wäre, hätten 36-Bit-Prozessoren die C-Sprache nicht implementieren können. Und sie können Java tatsächlich nicht implementieren! Daher erlaubte C der Sprache, mit einer Vielzahl verschiedener Computer zu arbeiten. Es ist unvermeidlich, dass dadurch Code erstellt werden kann, der nicht portierbar ist. Es ist eine Frage der Sprache.

gnasher729
quelle
Es ist möglich, 32-Bit-Arithmetik auf einem 36-Bit-Computer zu emulieren UND das Ergebnis jeder Operation mit 0xFFFFFFFF zu verknüpfen, um es auf 32-Bit abzuschneiden. Diese Maschinen könnten also Java implementieren, es wäre nur langsamer als wenn Java nichtet-basierte Typen zulässt.
Dan04
4

Java ist besonders portabel, da die Sprache auf die Java Virtual Machine abzielt, die, wie der Name schon sagt, keine echte Maschine ist . Da Sie eine virtuelle Maschine auf der Architektur vieler verschiedener Arten realer Maschinen implementieren können, ist ein JVM-basiertes Programm sehr portabel.

C hingegen wurde speziell für die Ausführung mit realer Hardware entwickelt, da es speziell für die Implementierung eines Betriebssystems erstellt wurde, das vollständigen Hardwarezugriff benötigt. Dies bedeutet, dass C-Code vom Design her nicht besonders portabel ist. Wenn Sie ein C-Programm von einer Plattform auf eine andere portieren, müssen verschiedene Teile, die für die Zielarchitektur spezifisch sind, bis zu dem einen oder anderen Grad neu geschrieben werden.

Mason Wheeler
quelle
7
C ist sehr portabel. Sie müssen nur auf der Zielplattform neu kompilieren und die wenigen Bits vermeiden, die spezifisch und absichtlich nicht portierbar sind.
Robert Harvey
5
@ RobertHarvey: ... wie Dinge, die so grundlegend sind wie die Größe verschiedener Grundelemente ? ;)
Mason Wheeler
2
Ja, diese Dinge. Es ist bedauerlich, dass das Problem besteht, aber die Sprache ist auf jede andere Weise vollständig portierbar, und es gibt Möglichkeiten, um sicherzustellen, dass primitive Größen auf allen Plattformen funktionieren.
Robert Harvey
3
@ RobertHarvey: Ich würde sagen, C macht es möglich, tragbare Programme zu schreiben, aber es macht es nicht von Natur aus einfach.
Doc Brown
2
@ RobertHarvey: Willst du einen Religionskrieg beginnen? ;-) Meine bevorzugte tragbare Sprache ist Python.
Doc Brown
3

Es gibt tatsächlich interpretierte Versionen von C , aber sie sind hauptsächlich für schnelle Experimente gedacht und nicht für Produktionssysteme.

Sie sind nicht alltäglich, denn warum würden Sie schließlich alle C-Eigenheiten erleiden, wenn Sie nicht eine kleine, schnelle und statische ausführbare Datei erhalten würden?

fortran
quelle
3

Theoretisch können sowohl C als auch Java zu nativem Code kompiliert, interpretiert oder zu einer virtuellen Maschine kompiliert werden.

Der technische Grund dafür, dass C nicht zu einer virtuellen Maschine kompiliert wird, ist, dass es einfach keine virtuelle Standard- C-Maschine gibt.

Und niemand scheint eine virtuelle C-Maschine definieren oder sogar auf die virtuelle Java-Maschine kompilieren zu wollen (was durchaus möglich ist). Wahrscheinlich, weil niemand, der C benutzt, seine unübertroffene Geschwindigkeit verlieren will. Wahrscheinlich auch, weil C in der Open-Source-Community am stärksten ist, die Portabilität durch Kompilierung (Verteilen und Neukompilieren der Quelle und Ausführen) problemlos durchführen kann, sodass sie die Portabilität der Ausführung (Verteilen und Ausführen einer Binärdatei) nicht als geschlossen empfinden Quellentwickler tun.

cmaster - Monica wieder einsetzen
quelle
1

Eigentlich ist das erledigt. Es gibt große Compiler, die die Kompilierung nach LLVM unterstützen (ich weiß, dass Clang dies tut, und ich glaube, dass GCC dies auch tut). Diese LLVM kann JIT-fähig sein, genauso wie Java-Code zu Bytecode kompiliert wird, der JIT-fähig ist.

Was Java jedoch im Vergleich zu C "plattformübergreifend" macht, ist, dass Java über eine große Laufzeitbibliothek verfügt, die auf viele Plattformen portiert wurde. C folgt diesem Paradigma ausdrücklich nicht.

Cort Ammon
quelle
C mit POSIX kann sehr portabel sein (auf jedes POSIX-System), wenn Sie vorsichtig codieren.
Basile Starynkevitch
0

Es gibt einige wesentliche Unterschiede zwischen Java und C. Java ist über die Java Virtual Machine (JVM) vom Betriebssystem isoliert. Die JVM abstrahiert das Betriebssystem vom Programm. Eine Java-Anwendung fragt möglicherweise die JVM nach einem Speicherblock, und die JVM fragt dann das Betriebssystem nach diesem Speicher. Es gibt viele JVMs für verschiedene Plattformen / Betriebssysteme. Mit der JVM kann dasselbe Java-Programm auf verschiedenen Plattformen ausgeführt werden.

Mit C gibt es keine Betriebssystemisolation. C-Programme werden (normalerweise) direkt auf dem Betriebssystem ausgeführt und führen direkte Betriebssystemaufrufe durch. Dadurch wird das C-Programm an ein bestimmtes Betriebssystem / eine bestimmte Plattform gebunden. Jedes nicht triviale Programm ruft das Betriebssystem auf. Darüber hinaus werden C-Programme in hardwarespezifischen Maschinencode kompiliert. Ein kompiliertes C-Programm für x86 kann nicht direkt auf einem ARM-Prozessor ausgeführt werden.

CurtisHx
quelle
1
Java wird zu plattformunabhängigem Bytecode kompiliert , der (zumindest theoretisch) von jeder JVM auf jeder Plattform ausgeführt werden kann. C wird für jede CPU, auf die Sie abzielen, in Assemblersprache kompiliert. Wenn Sie also auf die x86-Architektur abzielen, erstellt der C-Compiler einen x86-Assembler oder einen amd64-Assembler, wenn Sie auf diese Architektur abzielen, oder einen ARM-Assembler usw.). Dann wird die Assemblersprache in Objektdateien (eigentlich binärer Assembler) umgewandelt, die zu einer ausführbaren Datei verknüpft werden (je nach Zielcomputer verschiedene Formate).
Craig
1
In der Java-Sprachspezifikation gibt es nichts, was etwas über die JVM aussagt, und tatsächlich gibt es Implementierungen von Java ohne die JVM. Unter Android werden Java-Programme auf der Dalvik-VM (jetzt veraltet) oder der Android-Laufzeit ausgeführt. Es gibt Implementierungen von Java für die CLI, Implementierungen, die mit ECMAScript kompiliert werden, und Implementierungen, die mit nativem Code kompiliert werden. Es gibt C-Compiler, die mit der JVM kompiliert werden. Es gibt C-Compiler, die mit ECMAScript kompiliert werden. Es gibt C-Dolmetscher.
Jörg W Mittag