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

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

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

11 ответов


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

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

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

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

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

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

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

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


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

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

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


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

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

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

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

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

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


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

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

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


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

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

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

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

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


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

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

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

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


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

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

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

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


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

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

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

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

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

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


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


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

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


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