Qu'est-ce qui empêche C d'être compilé / interprété / JIT?

9

Java est souvent loué pour sa portabilité incroyable, ce qui, je suppose, est dû à la JVM. Ma question est de savoir ce qui empêche C d'être compilé / interprété / JIT'ed., Si c'est le cas, C peut également être écrit une fois et le faire fonctionner sur n'importe quel appareil que vous avez. mais ce n'est pas un mécanisme populaire pour traiter un programme C.

Quels sont les inconvénients de traiter C de cette manière, quels sont également les avantages de traiter Java de cette manière et de ne pas compiler en code machine, à part la portabilité bien sûr?

SphericalCow
la source
Votre question a déjà de très bonnes réponses ici: stackoverflow.com/questions/3925947/…
Doc Brown
2
@delnan mon point est que "ce qui empêche C d'être compilé / interprété / JIT'ed" perd vraiment son sens lorsque le langage peut cibler une machine virtuelle qui a JIT ou des situations où le vm identifiera les fonctionnalités manquantes dans le matériel et recompilera le code pour correspondre au matériel existant (comme avec OpenGL (écrit en C) sur OSX pour différentes cartes graphiques). Non, vous ne pouvez pas récupérer quelque chose compilé pour cibler llvm sur une machine et l'exécuter en tant que tel sur un autre processeur. Mais la ligne compilée / interprétée / JIT peut être assez floue.
1
Java est souvent excité pour sa portabilité incroyable. Il est portable sur les systèmes où la JVM a été compilée, c'est-à-dire les systèmes pour lesquels la JVM (écrite en C) a été compilée. Rien n'empêche de manipuler le code C de la même manière, sauf que personne ne voit assez d'avantages à le faire pour justifier l'effort.
Pete Becker
2
Je suis perplexe à propos de ce bit: "qu'est-ce qui empêche la compilation de C / [...]". Euh, rien?
Andres F.
1
Les compilateurs C sont assez rapides de nos jours, donc "make myprog.c; myprog" fonctionnera probablement plus rapidement que la plupart des interprètes.
James Anderson

Réponses:

18

C est ce que j'appellerais un langage de niveau intermédiaire. Son but est de servir d '«assembleur de très haut niveau», c'est pourquoi il fonctionne si bien en tant que cible de compilation et pourquoi il embrasse si bien la portabilité.

Historiquement, les interprètes ont généralement été utilisés avec des langages de haut niveau, dans le contexte des appels de méthode. Dans sa forme la plus simple, un interpréteur analyse simplement chaque mot-clé dans la langue source avec ses jetons associés, et les convertit en appels de méthode et paramètres. En pratique, ce que font la plupart des interprètes, c'est de convertir la langue source en une représentation intermédiaire, et c'est cette représentation qui est interprétée.

Qu'est-ce qui empêche C d'être interprété ou jeté? Rien. Mais ce n'est pas la raison d'être de C.

Robert Harvey
la source
6

Tout d'abord, il convient de noter que la JVM de Sun a été écrite en C. C est un langage très populaire lorsque la portabilité est nécessaire.

Le langage C est portable même si de nombreux programmes C ne le sont pas. En effet, C n'impose pas autant de restrictions au programmeur ni ne fait autant d'hypothèses. Si un programmeur C veut que ses programmes soient portables, il doit se mettre ces restrictions.

En pratique, ce n'est vraiment pas beaucoup plus difficile que de vivre avec les restrictions que Java vous impose. Il s'agit principalement de garder à l'esprit votre endianness et vos tailles primitives, et d'utiliser des bibliothèques portables comme GTK + au lieu de bibliothèques spécifiques à la plate-forme.

Vous pouvez créer une cible GTK + et un compilateur C qui prennent en charge une machine virtuelle, même probablement la JVM, et faire fonctionner le code existant avec très peu de modifications. En fait, sans le garbage collection, une machine virtuelle C serait probablement beaucoup plus simple. Pourquoi voudriez-vous, cependant?

L'inverse, la compilation de Java en code natif, est également réalisable. C'est essentiellement ce que fait le JIT. Pourquoi voudriez-vous, cependant? Je suis sûr qu'il existe des projets pour animaux de compagnie pour le faire «juste parce que», mais ils ne sont pas sérieusement utilisés.

Karl Bielefeldt
la source
5

Tu as dit:

Java est souvent loué pour sa portabilité incroyable, ce qui, je suppose, est dû à la JVM.

Et là, dans la première phrase, vous vous trompez. Java n'est pas portable à cause de la JVM. Java est portable, car le langage Java est défini d'une manière qui ne laisse à l'implémenteur aucune latitude quant au comportement d'un programme.

Par exemple, Java a deux types "int" (entier signé 32 bits) et "long" (entier signé 64 bits). C et C ++ ont "int" (signé au moins 16 bits), "long" (signé au moins 32 bits) et "long long" (signé au moins 64 bits). En effet, C est censé fonctionner sur de nombreux processeurs différents et leur permet de se comporter différemment.

C aurait pu définir des tailles fixes pour ces types. Si c'était le cas, les processeurs 36 bits n'auraient pas pu implémenter le langage C. Et ils ne peuvent en effet pas implémenter Java! C a donc permis au langage de fonctionner avec une variété d'ordinateurs différents. Il est inévitable que cela permette la création de code qui n'est pas portable. C'est une question de langue.

gnasher729
la source
Il est possible d'émuler une arithmétique 32 bits sur une machine 36 bits ET le résultat de chaque opération avec 0xFFFFFFFF pour le tronquer à 32 bits. Donc, ces machines pourraient implémenter Java, ce serait juste plus lent que si Java autorisait les types non basés.
dan04
4

Java est hautement portable, notamment parce que le langage cible la machine virtuelle Java, qui, comme son nom l'indique, n'est pas une vraie machine . Étant donné que vous pouvez implémenter une machine virtuelle sur l'architecture de nombreux types différents de machines réelles, un programme basé sur JVM est hautement portable.

C, d'autre part, est spécifiquement conçu pour être exécuté sur du matériel réel, car il a été créé dans le but spécifique de mettre en œuvre un système d'exploitation, qui nécessite un accès matériel complet. Cela signifie que le code C n'est pas particulièrement portable par conception , et lors du portage d'un programme C d'une plateforme à une autre, diverses parties spécifiques à l'architecture cible devront être réécrites à un degré ou un autre.

Mason Wheeler
la source
7
C est très portable. Il vous suffit de recompiler sur la plate-forme cible et d'éviter ces quelques bits qui ne sont pas spécifiquement et intentionnellement portables.
Robert Harvey
5
@RobertHarvey: ... comme des choses aussi fondamentales que la taille de diverses primitives? ;)
Mason Wheeler
2
Oui, ces choses. Il est regrettable que le problème existe, mais le langage est entièrement portable de toutes les autres manières, et il existe des moyens de s'assurer que les tailles primitives fonctionnent sur toutes les plates-formes.
Robert Harvey
3
@RobertHarvey: Je dirais que C permet d'écrire des programmes portables, mais cela ne le rend pas intrinsèquement facile.
Doc Brown
2
@RobertHarvey: voulez-vous déclencher une guerre de religion? ;-) Mon langage portable préféré est Python.
Doc Brown
3

Il existe en fait des versions interprétées de C , mais elles sont principalement destinées à être utilisées pour une expérimentation rapide plutôt que pour un système de production.

Ils ne sont pas courants, car après tout, pourquoi souffririez-vous de toutes les idiosyncrasies C sinon pour obtenir un petit exécutable rapide et statique?

fortran
la source
3

Théoriquement, C et Java peuvent tous deux être compilés en code natif, interprétés ou compilés sur une machine virtuelle.

La raison technique pour laquelle C n'est pas compilé sur une machine virtuelle, c'est qu'il n'y a tout simplement pas de machine C virtuelle standard .

Et personne ne semble vouloir définir une machine virtuelle C, ni même compiler vers la machine virtuelle Java (ce qui est parfaitement possible). Probablement parce que personne qui utilise C ne veut perdre sa vitesse inégalée. Probablement aussi parce que C est le plus fort dans la communauté open source qui peut facilement faire de la portabilité par compilation (distribuer et recompiler la source et exécuter), donc ils ne ressentent pas un tel besoin de portabilité d'exécution (distribuer et exécuter un binaire) comme fermé développeur source faire.

cmaster - réintégrer monica
la source
1

En fait, cela se fait. Il existe des compilateurs majeurs qui prennent en charge la compilation vers LLVM (je sais que clang le fait, et je pense que gcc le fait aussi). Ce LLVM peut être JIT comme le code Java est compilé en bytecode qui est JIT.

Cependant, ce qui rend java "multiplateforme" par rapport à C, c'est que Java a une grande bibliothèque d'exécution qui a été portée sur de nombreuses plates-formes. C ne suit pas explicitement ce paradigme.

Cort Ammon
la source
C avec POSIX peut être assez portable (vers n'importe quel système POSIX), si vous codez avec soin.
Basile Starynkevitch
0

Il existe des différences majeures entre Java et C. Java est isolé du système d'exploitation via la machine virtuelle java (JVM). La JVM extrait le système d'exploitation du programme. Une application java peut demander à la JVM un morceau de mémoire, et la JVM demande alors au système d'exploitation cette mémoire. Il existe de nombreuses JVM pour différentes plates-formes / systèmes d'exploitation. La JVM est ce qui permet au même programme java de s'exécuter sur différentes plateformes.

Avec C, il n'y a pas d'isolement du système d'exploitation. Les programmes C s'exécutent (généralement) directement sur le système d'exploitation, effectuant des appels directs au système d'exploitation. Cela crée des liens entre ce programme C et un système d'exploitation / plateforme spécifique. Tout programme non trivial va effectuer des appels dans le système d'exploitation. De plus, les programmes C sont compilés en code machine, qui est spécifique au matériel. Un programme C compilé pour x86 ne peut pas être exécuté directement sur un processeur ARM.

CurtisHx
la source
1
Java est compilé dans la plate-forme agnostique bytecode qui peut être ( en théorie, au moins) exécuté par une machine virtuelle Java sur toute plate - forme. C est compilé en langage d'assemblage pour le processeur que vous ciblez (donc si vous ciblez l'architecture x86, le compilateur C créera l'assembleur x86, ou l'assembleur amd64 si vous ciblez cette architecture, ou l'assembleur ARM, etc.). Ensuite, le langage d'assemblage est transformé en fichiers objets (assembleur binaire, en fait), qui sont liés dans un fichier exécutable (plusieurs formats différents, selon la machine cible).
Craig
1
Il n'y a rien dans la spécification du langage Java qui dit quoi que ce soit à propos de la JVM, et en fait, il existe des implémentations de Java sans la JVM. Sur Android, les programmes Java s'exécutent sur la machine virtuelle Dalvik (désormais obsolète) ou Android Runtime, il existe des implémentations de Java pour la CLI, des implémentations qui se compilent en ECMAScript et des implémentations qui se compilent en code natif. Il existe des compilateurs C qui compilent vers la JVM. Il existe des compilateurs C qui compilent vers ECMAScript. Il y a des interprètes C.
Jörg W Mittag