Скомпилированные и интерпретированные языки - PullRequest
256 голосов
/ 16 июля 2010

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

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

Ответы [ 12 ]

428 голосов
/ 16 июля 2010

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

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

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

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

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

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

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

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

94 голосов
/ 16 июля 2010

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

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

Таким образом, классификация языков по «скомпилированным» и «интерпретированным» не имеет особого смысла.

50 голосов
/ 16 июля 2010

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

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

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

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

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

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

24 голосов
/ 16 июля 2010

Экстремальные и простые случаи:

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

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

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

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

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

20 голосов
/ 21 января 2015

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

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

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

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

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

10 голосов
/ 20 мая 2014

Самое большое преимущество интерпретируемого исходного кода перед скомпилированным исходным кодом - ПОРТАТИВНОСТЬ .

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

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

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

7 голосов
/ 16 июля 2010

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

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

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

Но в настоящее время «скомпилировано и интерпретировано» - это не чёрно-белая проблема, между ними есть оттенки.Наивные, простые интерпретаторы в значительной степени вымерли.Во многих языках используется двухэтапный процесс, когда высокоуровневый код транслируется в независимый от платформы байт-код (который интерпретируется гораздо быстрее).Кроме того, у вас есть «своевременные компиляторы», которые компилируют код не чаще одного раза за запуск программы, иногда кэшируют результаты и даже разумно решают интерпретировать код, который выполняется редко, и проводят мощную оптимизацию для кода, который часто выполняется.Во время разработки отладчики способны переключать код внутри работающей программы даже для традиционно скомпилированных языков.

4 голосов
/ 16 июля 2010

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

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

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

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

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

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

2 голосов
/ 18 сентября 2016

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

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

2 голосов
/ 16 июля 2010

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

...