Скомпилированные и интерпретированные языки


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

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

11 230

11 ответов:

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

интерпретируемый язык-это язык, в котором инструкции не выполняются непосредственно целевой машиной, а вместо этого читаются и выполняются какой-либо другой программой (которая обычно - это написано на языке родная машина). Например, та же самая операция " + "будет распознана интерпретатором во время выполнения,который затем вызовет свою собственную функцию" add(a, b) "с соответствующими аргументами, которая затем выполнит инструкцию машинного кода" ADD".

вы можете делать все, что вы можете сделать на интерпретируемом языке на компилируемом языке, и наоборот - они оба Тьюринга. Однако оба они имеют преимущества и недостатки для реализации и использования.

Я собираюсь полностью обобщить (пуристы, простите меня!) но, грубо говоря, вот преимущества компилируемых языков:

  • более высокая производительность за счет прямого использования собственного кода целевой машины
  • возможность применения достаточно мощных оптимизаций на этапе компиляции

и вот преимущества интерпретируемых языков:

  • легче реализовать (написание хороших компиляторов очень тяжело!!)
  • нет необходимости запускать этап компиляции: можно выполнить код непосредственно "на лету"
  • может быть более удобным для динамических языков

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

сам язык не компилируется и не интерпретируется, только конкретная реализация языка. Java является прекрасным примером. Существует байт-кода на основе платформы (JVM), в родной компилятор (транспорт) и интерпретатором для надмножество Ява (БШ). Так что же такое Java сейчас? Байт-код-компилируется, нативно компилируется или интерпретируется?

другие языки, которые компилируются, а также интерпретируются, являются Scala, Haskell или Ocaml. Каждый из этих языков имеет интерактивный переводчик, а также компилятор в байт-код или машинный код.

поэтому обычно категоризация языков по "скомпилированным" и "интерпретированным" не имеет большого смысла.

начните думать в терминах a:взрыв из прошлого

давным-давно, давным-давно, там жили в стране вычислений интерпретаторы и компиляторы. Все виды суеты последовали за достоинствами один над другим. Общее мнение в это время было что-то вроде:

  • переводчик: Быстрая разработка (редактирование и запуск). Медленно выполняется, потому что каждый оператор должен быть интерпретирован в машинный код каждый время его выполнения (подумайте, что это означало для цикла, выполненного тысячи раз).
  • компилятор: медленная разработка (редактирование, компиляция, ссылка и запуск. Шаги компиляции / ссылки могут занять серьезное время). Быстрый во исполнение. Вся программа была уже в машинном коде.

разница в один или два порядка величины во время выполнения производительность существовала между интерпретируемой программой и скомпилированной программой. Другие отличительные очки, изменчивость времени выполнения код, например, также представлял некоторый интерес, но основной различие вращалось вокруг проблем производительности во время выполнения.

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

классическое отличие заключается в том, что компиляторы генерируют собственный машинный код, интерпретаторы читают исходный код и генерируется машинный код на лету с помощью какой-то системы времени выполнения. Сегодня осталось очень мало классических переводчиков - почти все они компиляция в байт-код (или некоторых других полу-компилированное состояние), который затем выполняется на виртуальной "машине".

крайние и простые случаи:

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

  • интерпретатор представит пользователю приглашение в цикле где он может вводить операторы или код, и при нажатии RUN или эквивалент интерпретатор будет проверять, сканировать, анализировать и интерпретативно выполнять каждую строку, пока программа не выполнит остановку или ошибку. Поскольку каждая строка обрабатывается сама по себе, и интерпретатор ничего не "узнает" от того, что видел эту строку раньше, усилия по преобразованию читаемого человеком языка в машинные инструкции возникают каждый раз для каждой строки, поэтому это собака медленно. С другой стороны, пользователь может проверять и иным образом взаимодействовать со своей программой всеми способами: изменение переменных, изменение кода, запуск в режимах трассировки или отладки... что угодно.

С теми, кто вне пути, позвольте мне объяснить, что жизнь больше не так проста. Например,

  • многие интерпретаторы будут предварительно компилировать код, который им дается, поэтому шаг перевода не должен повторяться снова и снова.
  • некоторые компиляторы компилируются не для конкретного процессора машинные инструкции, но для байт-кода, своего рода искусственный машинный код для фиктивной машины. Это делает скомпилированную программу немного более портативной, но требует интерпретатора байт-кода на каждой целевой системе.
  • интерпретаторы байт-кода (я смотрю на Java здесь) в последнее время имеют тенденцию перекомпилировать байт-код, который они получают для процессора целевого раздела непосредственно перед выполнением (называемый JIT). Чтобы сэкономить время, это часто делается только для кода, который часто выполняется (горячие точки).
  • некоторые системы, которые выглядят и действуют как интерпретаторы (например, Clojure), немедленно компилируют любой код, который они получают, но позволяют интерактивный доступ к среде программы. Это в основном удобство интерпретаторов со скоростью двоичной компиляции.
  • некоторые компиляторы на самом деле не компилируются, они просто предварительно переваривают и сжимают код. Я слышал некоторое время назад, что так работает Perl. Поэтому иногда компилятор просто делает немного работы, и большая ее часть все еще толкование.

в конце концов, в наши дни интерпретация и компиляция-это компромисс, причем время, затраченное (один раз) на компиляцию, часто вознаграждается лучшей производительностью во время выполнения, но интерпретационная среда дает больше возможностей для взаимодействия. Компиляция и интерпретация-это в основном вопрос того, как работа "понимания" программы разделена между различными процессами, и линия немного размыта в эти дни, поскольку языки и продукты пытаются предложить лучшее из эти два мира.

от http://www.quora.com/What-is-the-difference-between-compiled-and-interpreted-programming-languages

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

интерпретация-это метод, с помощью которого другая программа, переводчик, выполняющий операции от имени программы интерпретировать для того, чтобы запустить его. Если вы можете себе представить чтение программы и делать то, что он говорит делать шаг за шагом, скажем, на листе бумага, это как раз то, что делает переводчик. Общая причина интерпретировать программу-это то, что интерпретаторы относительно легко писать. Другая причина заключается в том, что интерпретатор может отслеживать, что программа пытается чтобы сделать так, как он работает, чтобы применить политику, скажем, для безопасность.

компиляция-это метод, при котором программа написана на одном языке ("исходный язык") переводится в программу на другом языке язык ("объектный язык"), что, надеюсь, означает то же самое как оригинальная программа. При выполнении перевода, он является общим для компилятор также попытается преобразовать программу способами, которые будут сделайте объектную программу быстрее (не меняя ее значения!). Один общая причина для компиляции программы заключается в том, что есть хороший способ запуск программ на объектном языке быстро и без накладных расходов интерпретации исходного языка на этом пути.

вы, возможно, догадались, основываясь на приведенных выше определениях, что эти два методы реализации не являются взаимоисключающими и даже могут быть дополнительный. Традиционно объектным языком компилятора был машинный код или что-то подобное, что относится к любому количеству языки программирования, понятные для конкретных компьютерных процессоров. Этот машинный код будет работать "на металле" (хотя можно было бы увидеть, если достаточно внимательно посмотреть, что "металл" работает очень похоже переводчик.) Однако сегодня очень часто используется компилятор для создайте объектный код, который должен быть интерпретирован-например, это это то, как Java используется (и иногда все еще работает). Есть компиляторы, которые переводят другие языки на JavaScript, который затем часто бегать в веб-браузер, который может интерпретировать JavaScript, или скомпилируйте его на виртуальной машине или в машинном коде. У нас также есть переводчики для машинного кода, который может использоваться для эмуляции одного вида оборудования другой. Или можно использовать компилятор для создания объектного кода, который является затем исходный код для другого компилятора, который может даже скомпилировать код в памяти как раз вовремя для его запуска, что в свою очередь . . . вы получаете идея. Есть много способов объединить эти понятия.

самое большое преимущество интерпретированного исходного кода над скомпилированным исходным кодом -мобильность.

Если ваш исходный код скомпилирован, вам нужно скомпилировать другой исполняемый файл для каждого типа процессора и/или платформы, на которой вы хотите запустить свою программу (например, один для Windows x86, один для Windows x64, один для Linux x64 и так далее). Кроме того, если ваш код не полностью соответствует стандартам и не использует какие-либо специфические для платформы функции/библиотеки, вы на самом деле нужно будет писать и поддерживать несколько баз кода!

Если ваш исходный код интерпретируется, вам нужно только написать его один раз, и он может быть интерпретирован и выполнен соответствующим интерпретатором на любой платформе! Это портативный! Обратите внимание, что интерпретатор сам по себе является исполняемой программой, которая и написано и скомпилировано для конкретной платформы.

преимуществом скомпилированного кода является то, что он скрывает исходный код от конечный пользователь (который может быть интеллектуальная собственность) потому что вместо развертывания исходного читаемого человеком исходного кода вы развертываете неясный двоичный исполняемый файл.

компилятор и интерпретатор выполняют одну и ту же работу: переводят язык программирования на другой язык pgoramming, обычно ближе к аппаратному обеспечению, часто непосредственно исполняемому машинному коду.

традиционно, "компилируется" означает, что этот перевод происходит все за один раз, делается разработчиком, и полученный исполняемый файл распространяется среди пользователей. Чистый пример: C++. Компиляция обычно занимает довольно много времени и пытается сделать много дорогих optmization так что в результате исполняемый файл работает быстрее. Конечные пользователи не имеют инструментов и знаний для компиляции материала сами, и исполняемый файл часто должен работать на различных аппаратных средствах, поэтому вы не можете выполнить много аппаратных оптимизаций. Во время разработки отдельный этап компиляции означает более длительный цикл обратной связи.

традиционно, "толковать" означает, что перевод происходит "на лету", когда пользователь хочет запустить программу. Чистый пример: ванильный PHP. Наивный интерпретатор должен разобрать и переводите каждый фрагмент кода каждый раз, когда он запускается, что делает его очень медленным. Он не может выполнять сложные, дорогостоящие оптимизации, потому что они занимают больше времени, чем время, сэкономленное при выполнении. Но он может полностью использовать возможности оборудования,. Отсутствие отдельного шага компиляции сокращает время обратной связи во время разработки.

но в настоящее время ", составленного и толковать" - это не черно-белый вопрос, Есть оттенки между ними. Наивные, простые интерпретаторы в значительной степени вымерли. Многие языки используют двухэтапный процесс, в котором высокоуровневый код переводится в независимый от платформы байт-код (который гораздо быстрее интерпретируется). Тогда у вас есть" Just in time compilers", которые компилируют код не более одного раза за запуск программы, иногда кэшируют результаты и даже разумно решают интерпретировать код, который выполняется редко, и делают мощные оптимизации для кода, который работает много. Во время разработки отладчики способны переключать код внутри запущенной программы даже для традиционно компилируемый язык.

во-первых, уточнение, Java не полностью статичен-скомпилирован и связан так, как C++. Он компилируется в байт-код, который затем интерпретируется JVM. JVM может пойти и сделать компиляцию just-in-time на родной машинный язык, но не обязательно это делать.

более того: я думаю, что интерактивность является главным практическим отличием. Поскольку все интерпретируется, вы можете взять небольшой отрывок кода, проанализировать и запустить его против текущего состояния среды. Таким образом, если вы уже выполнили код, который инициализировал переменную, у вас будет доступ к этой переменной и т. д. Он действительно поддается таким вещам, как функциональный стиль.

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

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

Что касается генерации исполняемых файлов, это имеет мало общего с ним, ИМХО. Часто можно создать исполняемый файл из скомпилированного языка. Но вы также можете создать исполняемый файл из интерпретируемого языка, за исключением того, что интерпретатор и среда выполнения уже упакованы в exectuable и скрыты от вас. Это означает, что вы, как правило, по-прежнему оплачиваете расходы на выполнение (хотя я уверен, что для некоторых языков есть способы перевести все в исполняемый файл дерева).

I не согласен с тем, что все языки могут быть интерактивными. Некоторые языки, такие как C, настолько привязаны к машине и всей структуре ссылок, что я не уверен, что вы можете построить полноценную интерактивную версию

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

The Python Book © 2015 Imagine Publishing Ltd, просто distunguishes разницу следующим намеком, упомянутым на странице 10 как:

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

компиляция-это процесс создания исполняемой программы из кода, написанного на компилируемом языке программирования. Компиляция позволяет компьютеру запускать и понимать программу без необходимости программного обеспечения, используемого для ее создания. Когда программа компилируется, она часто компилируется для определенной платформы (например, IBM platform), которая работает с IBM совместимыми компьютерами, но не с другими платформами (например, Apple platform). Первый компилятор был разработан Грейс Хоппер во время работы над Гарвардский Марк I компьютер. Сегодня большинство языков высокого уровня будут включать свой собственный компилятор или иметь доступные наборы инструментов, которые могут быть использованы для компиляции программы. Хороший пример компилятора, который используется с Java в Eclipse и пример компилятора, который используется в C и C++ - это команда ССЗ. В зависимости от того, насколько велика программа, она должна занять несколько секунд или минут для компиляции, и если при компиляции не возникает ошибок, создается исполняемый файл.проверьте эту информацию