Что мешает C быть скомпилированным / интерпретированным / JIT'ом?

9

Java часто хвалят за ее удивительную мобильность, которая, как я полагаю, обусловлена ​​JVM. Мой вопрос заключается в том, что мешает C быть скомпилированным / интерпретированным / JIT'ом ..., если это так, C также может быть записан один раз и заставить его работать на любом устройстве, которое у вас есть. но это не популярный механизм для обработки программы на Си.

Каковы недостатки обработки C таким способом, а также каковы преимущества обработки Java таким образом и отсутствия компиляции в машинный код, кроме, конечно, переносимости?

SphericalCow
источник
На ваш вопрос уже есть несколько очень хороших ответов: stackoverflow.com/questions/3925947/…
Док Браун
2
@delnan, я хочу сказать, что «то, что мешает компиляции / интерпретации C / JIT'у C, действительно теряет смысл, когда язык может быть нацелен на виртуальную машину с JIT или ситуации, когда vm идентифицирует отсутствующие функции в аппаратном обеспечении и перекомпилирует код для соответствия существующему оборудованию (например, с OpenGL (написано на C) в OSX для разных видеокарт). Нет, вы не можете получить что-то скомпилированное для работы с llvm на одном компьютере и запустить его как таковое на другом процессоре. Но скомпилированная / интерпретированная строка / JIT может быть довольно размытой.
1
Java часто раскручивается из- за ее удивительной мобильности. Он переносим на системы, в которых была скомпилирована JVM, то есть на системы, для которых была скомпилирована JVM (написанная на C). Ничто не мешает обрабатывать C-код таким же образом, за исключением того, что никто не видит достаточной выгоды от этого, чтобы оправдать усилия.
Пит Беккер
2
Я озадачен этим битом: «что мешает компилировать C / [...]». Ничего?
Андрес Ф.
1
Компиляторы C в наши дни довольно быстрые, поэтому «make myprog.c; myprog», вероятно, будет работать быстрее, чем большинство интерпретаторов.
Джеймс Андерсон

Ответы:

18

C это то, что я бы назвал языком среднего уровня. Его цель - служить «ассемблером очень высокого уровня», поэтому он так хорошо работает как цель компилятора и почему он так хорошо переносит переносимость.

Исторически интерпретаторы обычно использовались с языками высокого уровня в контексте вызовов методов. В простейшей форме интерпретатор просто анализирует каждое ключевое слово в исходном языке вместе со связанными с ним токенами и преобразует его в вызовы методов и параметры. На практике большинство интерпретаторов конвертирует исходный язык в некоторое промежуточное представление, и именно это представление интерпретируется.

Что мешает C быть интерпретированным или скомбинированным? Ничего. Но это не смысл существования C.

Роберт Харви
источник
6

Прежде всего, стоит отметить, что JVM от Sun была написана на языке C. Язык C очень популярен, когда требуется переносимость.

C язык является переносным , хотя многие C программа не является. Это потому, что C не накладывает столько ограничений на программиста и не делает столько предположений. Если программист на Си хочет, чтобы его программы были переносимыми, он должен наложить эти ограничения на себя.

На практике это на самом деле не намного сложнее, чем жить с ограничениями, которые на вас навязывает Java. Это в основном вопрос того, чтобы помнить о вашем порядке байтов и примитивах и использовать переносные библиотеки, такие как GTK +, вместо библиотек, специфичных для платформы.

Вы можете создать компилятор GTK + target и C, который поддерживает виртуальную машину, даже, возможно, JVM, и заставить существующий код работать с очень небольшими изменениями. На самом деле, без сборки мусора виртуальная машина C, вероятно, была бы намного проще. Почему вы хотите, хотя?

Обратное, компиляция Java в нативный код, также выполнимо. Это в основном то, что делает JIT. Почему вы хотите, хотя? Я уверен, что есть любимые проекты, чтобы сделать это «просто потому что», но они не используются серьезно.

Карл Билефельдт
источник
5

Вы сказали:

Java часто хвалят за ее удивительную мобильность, которая, как я полагаю, обусловлена ​​JVM.

И там, в первом предложении, вы не правы. Java не переносима из-за JVM. Java является переносимым, потому что язык Java определен так, что не оставляет разработчику никакой свободы в поведении программы.

Например, Java имеет два типа «int» (32-разрядное целое число со знаком) и «long» (64-разрядное целое число со знаком). C и C ++ имеют значения «int» (со знаком не менее 16 бит), «long» (со знаком не менее 32 бит) и «long long» (со знаком не менее 64 бит). Это потому, что C должен работать на разных процессорах и позволяет им вести себя по-разному.

C мог бы определить фиксированные размеры для этих типов. Если бы это было так, тогда 36-битные процессоры не могли бы реализовать язык Си. И они действительно не могут реализовать Java! Таким образом, C позволил языку работать с различными компьютерами. Это неизбежно, что это позволяет создавать код, который не является переносимым. Это вопрос языка.

gnasher729
источник
32-разрядную арифметику можно эмулировать на 36-разрядной машине, а результат каждой операции с помощью 0xFFFFFFFF можно обрезать до 32-разрядной. Таким образом, эти машины могли бы реализовывать Java, это было бы медленнее, чем если бы Java допускала типы, не основанные на данных.
dan04
4

Java обладает высокой переносимостью, в частности, потому что язык нацелен на виртуальную машину Java, которая, как следует из названия, не является реальной машиной . Поскольку вы можете реализовать виртуальную машину на архитектуре множества различных типов реальных машин, программа на основе JVM обладает высокой переносимостью.

C, с другой стороны, специально разработан для работы на реальном оборудовании, потому что он был создан для конкретной цели реализации операционной системы, которая требует полного аппаратного доступа. Это означает, что код C не является особенно переносимым по своей структуре , и при переносе программы на C с одной платформы на другую необходимо переписать различные части, специфичные для целевой архитектуры, в той или иной степени.

Мейсон Уилер
источник
7
С очень портативен. Вам просто нужно перекомпилировать на целевой платформе и избегать тех немногих битов, которые специально и намеренно не переносимы.
Роберт Харви
5
@RobertHarvey: ... такие фундаментальные вещи, как размер различных примитивов? ;)
Мейсон Уилер
2
Да, эти вещи К сожалению, проблема существует, но язык полностью переносим во всех других отношениях, и есть способы убедиться, что примитивные размеры работают на всех платформах.
Роберт Харви
3
@RobertHarvey: Я бы сказал, что C позволяет писать переносимые программы, но это не делает его по своей природе простым.
Док Браун
2
@RobertHarvey: ты хочешь начать религиозную войну? ;-) Мой любимый переносимый язык - Python.
Док Браун
3

На самом деле существуют интерпретируемые версии C , но в основном они предназначены для быстрого эксперимента, а не для производственной системы.

Они не являются обычным делом, потому что, в конце концов, зачем вам страдать от всех специфических особенностей, если не получить небольшой, быстрый и статичный исполняемый файл?

Фортран
источник
3

Теоретически и C, и Java могут быть скомпилированы в собственный код, интерпретированы или скомпилированы в виртуальную машину.

Техническая причина того, что C не скомпилирован в виртуальную машину, заключается в том, что просто нет стандартной виртуальной машины C.

И, похоже, никто не хочет определять виртуальную машину C или даже компилировать ее в виртуальную машину Java (что вполне возможно). Возможно, потому что никто, кто использует C, не хочет терять свою непревзойденную скорость. Вероятно также, потому что C является самым сильным в сообществе открытого исходного кода, которое может легко сделать переносимость компиляцией (распределить и перекомпилировать исходный код и выполнить), поэтому они не чувствуют такой необходимости переносимости выполнения (распространять и выполнять двоичный файл) как закрытое Разработчик исходного кода.

cmaster - восстановить монику
источник
1

На самом деле, это сделано. Существуют основные компиляторы, которые поддерживают компиляцию в LLVM (я знаю, что clang делает, и я верю, что gcc делает то же самое). Этот LLVM может быть JIT, как Java-код скомпилирован в байт-код, который является JIT.

Однако то, что делает Java кроссплатформенным по сравнению с C, это то, что Java имеет большую библиотеку времени выполнения, которая была портирована на многие платформы. С явно не следует этой парадигме.

Корт Аммон
источник
C с POSIX может быть довольно переносимым (для любой системы POSIX), если вы кодируете с осторожностью.
Василий Старынкевич
0

Есть некоторые существенные различия между Java и C. Java изолируется от операционной системы через виртуальную машину Java (JVM). JVM абстрагирует операционную систему от программы. Java-приложение может запросить у JVM кусок памяти, а затем JVM запросит у ОС эту память. Существует много JVM для разных платформ / операционных систем. JVM - это то, что позволяет одной и той же Java-программе работать на разных платформах.

С C нет изоляции ОС. Программы на C (обычно) запускаются прямо поверх операционной системы, выполняя прямые вызовы операционной системы. Это связывает эту программу на C с конкретной операционной системой / платформой. Любая нетривиальная программа собирается совершать звонки в операционную систему. Кроме того, C-программы компилируются в машинный код, который зависит от аппаратного обеспечения. Скомпилированная программа C для x86 не может быть напрямую запущена на процессоре ARM.

CurtisHx
источник
1
Java компилируется в независимый от платформы байт - код, который может (по крайней мере теоретически) выполняться любой JVM на любой платформе. C компилируется в язык ассемблера для любого процессора, на который вы нацелены (поэтому, если вы нацеливаетесь на архитектуру x86, компилятор C создаст ассемблер x86 или ассемблер amd64, если вы ориентируетесь на эту архитектуру, или ассемблер ARM и т. Д.). Затем язык ассемблера превращается в объектные файлы (в действительности, двоичный ассемблер), которые связаны в исполняемый файл (несколько разных форматов, в зависимости от целевой машины).
Крейг
1
В Спецификации языка Java нет ничего, что говорило бы о JVM, и на самом деле, есть реализации Java без JVM. В Android Java-программы выполняются на виртуальной машине Dalvik (в настоящее время устарела) или в среде выполнения Android, есть реализации Java для CLI, реализации, компилируемые в ECMAScript, и реализации, компилируемые в нативный код. Есть компиляторы C, которые компилируются в JVM. Есть компиляторы C, которые компилируются в ECMAScript. Есть C переводчики.
Йорг Миттаг