¿Qué impide que C se compile / interprete / JIT'ed?

9

Java es a menudo elogiado por su increíble portabilidad, que supongo que se debe a la JVM. Mi pregunta es qué impide que C se compile / interprete / JITE ..., si es así, C también se puede escribir una vez y hacer que funcione en cualquier dispositivo que tenga. pero este no es un mecanismo popular para procesar un programa en C.

¿Cuáles son las desventajas de procesar C de esta manera, y también cuáles son las ventajas de procesar Java de esta manera y no compilar en código máquina, aparte de la portabilidad, por supuesto?

Vaca Esférica
fuente
Su pregunta ya tiene algunas respuestas muy buenas aquí: stackoverflow.com/questions/3925947/…
Doc Brown
2
@delnan mi punto es que "lo que impide que C se compile / interprete / JIT'ed" realmente pierde su significado cuando el lenguaje puede apuntar a una máquina virtual que tiene JIT o situaciones en las que el vm identificará características faltantes en el hardware y recompilará el código para que coincida con el hardware existente (como con OpenGL (escrito en C) en OSX para diferentes tarjetas gráficas). No, no puede tomar algo compilado para apuntar a llvm en una máquina y ejecutarlo como tal en otro procesador. Pero la línea compilada / interpretada / JIT puede ser bastante borrosa.
1
Java a menudo se promociona por su increíble portabilidad. Es portátil para sistemas donde se ha compilado la JVM, es decir, sistemas para los que se ha compilado la JVM (escrita en C). No hay nada que impida manejar el código C de la misma manera, excepto que nadie ve suficientes beneficios al hacerlo para justificar el esfuerzo.
Pete Becker
2
Estoy desconcertado sobre este bit: "lo que impide que C se compile / [...]". ¿Nada?
Andres F.
1
Los compiladores de C son bastante rápidos en estos días, por lo que "make myprog.c; myprog" probablemente se ejecutará más rápido que la mayoría de los intérpretes.
James Anderson

Respuestas:

18

C es lo que yo llamaría un lenguaje de nivel medio. Su propósito es servir como un "ensamblador de muy alto nivel", por lo que funciona tan bien como un compilador de destino, y por qué abarca tan bien la portabilidad.

Históricamente, los intérpretes se han utilizado típicamente con lenguajes de alto nivel, en el contexto de llamadas a métodos. En su forma más simple, un intérprete simplemente analiza cada palabra clave en el idioma fuente junto con sus tokens asociados, y los convierte en llamadas a métodos y parámetros. En la práctica, lo que hacen la mayoría de los intérpretes es convertir el lenguaje fuente en alguna representación intermedia, y es esa representación la que se interpreta.

¿Qué impide que C sea interpretado o sacudido? Nada. Pero esa no es la razón de ser de C.

Robert Harvey
fuente
6

En primer lugar, vale la pena señalar que JVM de Sun fue escrito en C. C es un lenguaje muy popular cuando se necesita portabilidad.

El lenguaje C es portátil a pesar de que muchos programas C no lo son. Esto se debe a que C no impone tantas restricciones al programador ni hace tantas suposiciones. Si un programador C quiere que sus programas sean portátiles, debe imponerse esas restricciones.

En la práctica, eso realmente no es mucho más difícil que vivir con las restricciones que Java te impone. Es principalmente una cuestión de ser consciente de su endianness y tamaños primitivos, y usar bibliotecas portátiles como GTK + en lugar de bibliotecas específicas de la plataforma.

Podría hacer un compilador de GTK + y C que admitiera una máquina virtual, incluso probablemente la JVM, y obtener el código existente para trabajar con muy pocos cambios. De hecho, sin la recolección de basura, una máquina virtual en C probablemente sería mucho más simple. ¿Pero por qué querrías hacerlo?

Lo contrario, compilar Java en código nativo, también es factible. Eso es básicamente lo que hace el JIT. ¿Pero por qué querrías hacerlo? Estoy seguro de que hay proyectos favoritos para hacerlo "solo porque", pero no están en uso serio.

Karl Bielefeldt
fuente
5

Tu dijiste:

Java es a menudo elogiado por su increíble portabilidad, que supongo que se debe a la JVM.

Y allí, dentro de la primera oración, estás equivocado. Java no es portátil debido a la JVM. Java es portátil, porque el lenguaje Java se define de una manera que no deja al implementador ningún margen de maniobra sobre cómo puede comportarse un programa.

Como ejemplo, Java tiene dos tipos "int" (entero de 32 bits con signo) y "largo" (entero de 64 bits con signo). C y C ++ tienen "int" (firmado al menos 16 bits), "largo" (firmado al menos 32 bits) y "largo largo" (firmado al menos 64 bits). Esto se debe a que se supone que C se ejecuta en muchos procesadores diferentes y les permite comportarse de manera diferente.

C podría haber definido tamaños fijos para estos tipos. Si lo hubiera hecho, los procesadores de 36 bits no podrían haber implementado el lenguaje C. ¡Y de hecho no pueden implementar Java! Entonces, C permitió que el lenguaje funcionara con una variedad de computadoras diferentes. Es inevitable que esto permita la creación de código que no sea portátil. Es una cuestión de idioma.

gnasher729
fuente
Es posible emular la aritmética de 32 bits en una máquina de 36 bits y obtener el resultado de cada operación con 0xFFFFFFFF para truncarlo a 32 bits. Entonces, estas máquinas podrían implementar Java, sería más lento que si Java permitiera tipos no basados.
dan04
4

Java es altamente portátil específicamente porque el lenguaje se dirige a la Máquina Virtual Java, que, como su nombre lo indica, no es una máquina real . Como puede implementar una máquina virtual en la arquitectura de muchos tipos diferentes de máquinas reales, un programa basado en JVM es altamente portátil.

C, por otro lado, está específicamente diseñado para ejecutarse contra hardware real, porque fue creado con el propósito específico de implementar un sistema operativo, que necesita acceso completo al hardware. Esto significa que el código C no es particularmente portátil por diseño , y al portar un programa C de una plataforma a otra, varias partes que son específicas de la arquitectura de destino deberán reescribirse en un grado u otro.

Mason Wheeler
fuente
77
C es altamente portátil. Solo tiene que volver a compilar en la plataforma de destino y evitar esos pocos bits que no son portátiles de manera específica e intencional.
Robert Harvey
55
@RobertHarvey: ... como cosas tan fundamentales como el tamaño de varias primitivas? ;)
Mason Wheeler
2
Si, esas cosas. Es desafortunado que el problema exista, pero el lenguaje es totalmente portátil de cualquier otra manera, y hay formas de asegurarse de que los tamaños primitivos funcionen en todas las plataformas.
Robert Harvey
3
@RobertHarvey: Diría que C hace posible escribir programas portátiles, pero no lo hace inherentemente fácil.
Doc Brown
2
@RobertHarvey: ¿quieres comenzar una guerra religiosa? ;-) Mi lenguaje portátil favorito es Python.
Doc Brown
3

En realidad, hay versiones interpretadas de C , pero en su mayoría están destinadas a ser utilizadas para la experimentación rápida en lugar del sistema de producción.

No son comunes, porque después de todo, ¿por qué sufrirías todas las idiosincrasias de C si no es para obtener un ejecutable pequeño, rápido y estático?

fortran
fuente
3

Teóricamente, tanto C como Java pueden compilarse en código nativo, interpretarse o compilarse en una máquina virtual.

La razón técnica de que C no se compila en una máquina virtual es que simplemente no hay una máquina virtual C estándar .

Y nadie parece querer definir una máquina virtual en C, o incluso compilar en la máquina virtual Java (que es perfectamente posible). Probablemente porque nadie que usa C quiere perder su velocidad inigualable. Probablemente también porque C es más fuerte en la comunidad de código abierto que puede realizar fácilmente la portabilidad mediante compilación (distribuir y recompilar la fuente y ejecutar), por lo que no sienten la necesidad de la portabilidad de ejecución (distribuir y ejecutar un binario) como cerrado desarrollador de origen hacer.

cmaster - restablecer monica
fuente
1

En realidad, esto está hecho. Hay compiladores importantes que admiten la compilación de LLVM (sé que clang lo hace, y creo que gcc también). Ese LLVM puede ser JIT'd tal como el código Java se compila en bytecode que es JIT'd.

Sin embargo, lo que hace que Java sea "multiplataforma" en comparación con C es que Java tiene una gran biblioteca de tiempo de ejecución que se ha portado a muchas plataformas. C explícitamente no sigue este paradigma.

Cort Ammon
fuente
C con POSIX puede ser bastante portátil (para cualquier sistema POSIX), si codifica con cuidado.
Basile Starynkevitch
0

Hay algunas diferencias importantes entre Java y C. Java está aislado del sistema operativo a través de la máquina virtual Java (JVM). La JVM abstrae el sistema operativo del programa. Una aplicación de Java puede pedirle a la JVM un trozo de memoria, y la JVM le pide al sistema operativo esa memoria. Hay muchas JVM para diferentes plataformas / sistemas operativos. El JVM es lo que permite que el mismo programa Java se ejecute en diferentes plataformas.

Con C, no hay aislamiento del sistema operativo. Los programas C (generalmente) se ejecutan directamente sobre el sistema operativo, haciendo llamadas directas al sistema operativo. Esto vincula ese programa C a un sistema operativo / plataforma específico. Cualquier programa no trivial hará llamadas al sistema operativo. Además, los programas C se compilan en código máquina, que es específico del hardware. Un programa C compilado para x86 no se puede ejecutar directamente en un procesador ARM.

CurtisHx
fuente
1
Java se compila en un bytecode independiente de la plataforma que puede ser (en teoría, al menos) ejecutado por cualquier JVM en cualquier plataforma. C se compila en lenguaje ensamblador para cualquier CPU que esté apuntando (por lo tanto, si está apuntando a la arquitectura x86, el compilador C creará un ensamblador x86 o un ensamblador amd64 si está apuntando a esa arquitectura, o ensamblador ARM, etc.). Luego, el lenguaje ensamblador se convierte en archivos de objetos (ensamblador binario, realmente), que están vinculados a un archivo ejecutable (varios formatos diferentes, dependiendo de la máquina de destino).
Craig
1
No hay nada en la Especificación del lenguaje Java que diga algo sobre la JVM, y de hecho, hay implementaciones de Java sin la JVM. En Android, los programas Java se ejecutan en la máquina virtual Dalvik (ahora obsoleta) o en Android Runtime, hay implementaciones de Java para la CLI, implementaciones que compilan a ECMAScript e implementaciones que compilan a código nativo. Hay compiladores de C que compilan a la JVM. Hay compiladores de C que compilan a ECMAScript. Hay intérpretes de C.
Jörg W Mittag