web-dev-qa-db-ja.com

コンパイル言語と解釈言語

違いをもっとよく理解しようとしています。私はオンラインでたくさんの説明を見つけました、しかしそれらは実際的な意味よりもむしろ抽象的な違いに向かって傾向があります。

私のプログラミング経験の大部分は、CPython(動的、解釈済み)、およびJava(静的、コンパイル済み)の経験があります。しかし、私は他の種類の解釈されコンパイルされた言語があることを理解しています。実行可能ファイルはコンパイルされた言語で書かれたプログラムから配布できるという事実とは別に、それぞれのタイプに何か利点/不利な点がありますか?多くの場合、インタプリタ言語は対話的に使用できると主張する人がいますが、コンパイルされた言語にも対話的な実装を含めることができると思います。

255
chimeracoder

コンパイルされた言語は、いったんコンパイルされると、プログラムがターゲットマシンの命令で表現されるものです。たとえば、ソースコード内の追加の "+"操作は、マシンコード内の "ADD"命令に直接変換できます。

インタプリタ言語とは、命令がターゲットマシンによって直接実行されるのではなく、他のプログラム(通常はネイティブマシンの言語で書かれたis)によって読み取られ実行される言語です。例えば、同じ "+"操作が実行時にインタプリタによって認識され、それが次に適切な引数でそれ自身の "add(a、b)"関数を呼び出し、それが次にマシンコード "ADD"命令を実行する。

インタプリタ言語でできることなら何でもコンパイル言語でもその逆もできます - どちらもチューリング完全です。しかしながら、両方とも実施および使用のために長所と短所がある。

私は完全に一般化するつもりです(純粋主義者は私を許します!)、しかし、大体、ここにコンパイルされた言語の利点があります:

  • ターゲットマシンのネイティブコードを直接使用してパフォーマンスを向上
  • コンパイル段階で非常に強力な最適化を適用する機会

そして、これがインタプリタ言語の利点です。

  • 実装が簡単(良いコンパイラを書くのはとても難しいです。)
  • コンパイル段階を実行する必要はありません。コードを「その場で」直接実行できます。
  • 動的言語にはもっと便利になる

バイトコードコンパイルのような最新の技術はいくらか複雑さを増すことに注意してください - ここで起こることはコンパイラが基礎となるハードウェアと同じではない「仮想マシン」をターゲットにするということです。その後、これらの仮想マシン命令は、後の段階で(例えば、Java(登録商標)JVM JITコンパイラによって行われるように)ネイティブコードを取得するために再びコンパイルすることができる。

427
mikera

言語自体はコンパイルも解釈もされておらず、言語の特定の実装のみが行われています。 Javaはその好例です。バイトコードベースのプラットフォーム(JVM)、ネイティブコンパイラ(gcj)、およびJavaのスーパーセット用のインタプリタ(bsh)があります。それでは今Javaは何ですか?バイトコードコンパイル済み、ネイティブコンパイル済み、または解釈済みのいずれか

他の言語は、翻訳も翻訳もされていますが、Scala、Haskell、Ocamlです。これらの各言語には、対話型インタプリタ、およびバイトコードまたはネイティブのマシンコードへのコンパイラがあります。

そのため、一般的に「コンパイル済み」と「解釈済み」で言語を分類するのはあまり意味がありません。

94
lunaryorn

Aの観点から考え始める:過去からの爆発

むかしむかし、ずっと前に、コンピューティングのインタプリタとコンパイラの国に住んでいました。あらゆる種類の大騒ぎが、互いのメリットよりもメリットがありました。当時の一般的な意見は次のようなものでした。

  • インタプリタ:開発が速い(編集と実行)。各ステートメントは、実行されるたびにマシンコードに変換される必要があるため、実行に時間がかかります(これがループの何千回もの実行を意味すると考えてください)。
  • コンパイラ:開発が遅い(編集、コンパイル、リンク、実行。コンパイル/リンクの手順は大変な時間がかかります)。実行が速いです。プログラム全体はすでにネイティブのマシンコードで書かれていました。

インタプリタプログラムとコンパイルされたプログラムの間には、実行時性能に1桁から2桁の違いがありました。他の際立った点、例えばコードの実行時の変更可能性もまた興味深いものでしたが、大きな違いは実行時のパフォーマンスの問題を中心に展開されました。

今日、景観は、コンパイルされた/解釈された区別がほとんど無関係である程度まで進化しました。多くのコンパイル言語は、完全に機械語ベースではないランタイムサービスを要求します。また、ほとんどのインタプリタ言語は実行前にバイトコードに "コンパイル"されます。バイトコードインタプリタは非常に効率的であり、実行速度の観点からコンパイラ生成コードに匹敵します。

古典的な違いは、コンパイラがネイティブの機械語コードを生成し、インタプリタがある種のランタイムシステムを使用してその場でソースコードを読み取り、機械語コードを生成することです。今日では非常に少数の古典的なインタプリタが残っています - それらのほとんど全てが仮想の "マシン"上で走るバイトコード(あるいは他の何らかの半コンパイル状態)にコンパイルされます。

50
NealB

極端で単純なケース:

  • コンパイラは、ターゲットマシンのネイティブ実行可能形式でバイナリ実行可能ファイルを生成します。このバイナリファイルには、システムライブラリを除くすべての必要なリソースが含まれています。コードはターゲットマシンのCPUのネイティブコードであるため、これ以上の準備や処理を行わなくても実行できます。

  • インタプリタは、文またはコードを入力できるループでユーザにプロンプ​​トを表示し、RUNまたはそれに相当するものを押すと、プログラムが停止点またはプログラムが停止するまで各行を調べ、スキャンし、解析し、解釈的に実行します。エラー。各行はそれぞれ独自に扱われ、インタプリタはその行を以前に見たことから何も「学ぶ」ことはしないので、人間が読める言語を機械命令に変換する努力は毎回毎回発生します。明るい面としては、ユーザーは自分のプログラムをいろいろな方法で検査したり、対話したりすることができます。変数の変更、コードの変更、トレースモードまたはデバッグモードでの実行など。

邪魔にならないようにして、人生はそれほど単純ではなくなったことを説明させてください。例えば、

  • 多くのインタプリタは与えられたコードをプリコンパイルするので、翻訳のステップを何度も繰り返す必要はありません。
  • 一部のコンパイラは、CPU固有のマシン命令ではなく、仮想マシンの一種の人工マシンコードであるバイトコードにコンパイルします。これにより、コンパイルされたプログラムはもう少し移植性がよくなりますが、すべてのターゲットシステムにバイトコードインタプリタが必要になります。
  • バイトコードインタプリタ(私はここではJavaを見ています)は最近、実行直前(JITと呼ばれる)にターゲットセクションのCPU用に取得したバイトコードを再コンパイルする傾向があります。時間を節約するために、これはよく実行されるコード(ホットスポット)に対してのみ行われます。
  • インタプリタのように見え、振る舞うシステム(例えばClojure)の中には、取得したコードをただちにコンパイルするものもありますが、プログラムの環境への対話式アクセスを可能にするものがあります。それは基本的にバイナリコンパイルの速度を持つインタプリタの便利さです。
  • 一部のコンパイラは実際にはコンパイルしません。コードを事前にダイジェストして圧縮します。私はしばらく前にPerlが機能する方法を聞いたことがあります。だから時々コンパイラはちょっとした仕事をしているだけでそれの大部分はまだ解釈です。

結局、最近では、コンパイルとコンパイルはトレードオフの関係にあり、コンパイルに費やされた時間は実行時のパフォーマンスの向上によってしばしば見返されますが、解釈環境は対話の機会を増やすことになります。コンパイルと解釈の大部分は、プログラムを「理解する」という作業が異なるプロセス間でどのように分けられているかという問題であり、言語と製品が両方の長所を提供しようとしているため、最近の行は少しぼやけています。

24
Carl Smotricz

から http://www.quora.com/What-is-the-dference- between-compiled-and-interpreted-programming-languages

「コンパイルされたプログラミング言語」と「解釈されたプログラミング言語」は意味のある概念ではないため、違いはありません。どんなプログラミング言語でも、そして私は本当にあらゆる意味で、解釈またはコンパイルすることができます。したがって、解釈とコンパイルは実装技術であり、言語の属性ではありません。

解釈は、それを実行するために解釈されているプログラムに代わって別のプログラム、つまりインタプリタが操作を実行する手法です。あなたがプログラムを読んで、そしてそれが段階的にするために言うことを言うのを想像することができるならば、一枚のスクラッチペーパーの上で言いなさい、それはまさにインタプリタもするものです。プログラムを解釈する一般的な理由は、インタプリタは比較的書きやすいということです。もう1つの理由は、インタプリタがプログラムの実行時に何をしようとしているのかを監視して、たとえばセキュリティのためにポリシーを強制できるからです。

コンパイルは、ある言語(「ソース言語」)で書かれたプログラムを別の言語(「オブジェクト言語」)のプログラムに翻訳する手法です。これは元のプログラムと同じことを意味しています。翻訳をしている間、コンパイラが目的プログラムをより速くするような方法で(その意味を変えることなしに)プログラムを変換することを試みるのも一般的です。プログラムをコンパイルする一般的な理由は、ソース言語を途中で解釈するというオーバーヘッドをかけずに、オブジェクト言語でプログラムを迅速に実行するための優れた方法がいくつかあることです。

上記の定義に基づいて、これら2つの実装方法は相互に排他的ではなく、補足的なものである可能性もあります。伝統的に、コンパイラのオブジェクト言語はマシンコードまたはそれに類似したものであり、それは特定のコンピュータCPUによって理解される任意の数のプログラミング言語を指します。その場合、マシンコードは「オンザメタル」で実行されます(ただし、「メタル」はインタプリタのように機能することがよくわかりますが、これを確認することもできます)。しかし今日では、解釈されることを意図したオブジェクトコードを生成するためにコンパイラを使用することは非常に一般的です。例えば、これはJavaが(そして時々まだ)動作する方法です。他の言語をJavaScriptに翻訳するコンパイラがあります。それは、その後Webブラウザで実行されることが多く、JavaScriptを解釈したり、仮想マシンやネイティブコードにコンパイルしたりする可能性があります。私たちには、ある種類のハードウェアを別のハードウェアにエミュレートするために使用できる、マシンコード用のインタプリタもあります。または、コンパイラを使用してオブジェクトコードを生成し、それが別のコンパイラのソースコードになることもあります。これは、実行するのに間に合うようにコードをメモリ内でコンパイルすることもあります。 。 。あなたはアイデアを得ます。これらの概念を組み合わせる方法はたくさんあります。

20
Bhavin Shah

コンパイル済みソースコードに対するインタープリターソースコードの最大の利点はポータビリティです。

ソースコードをコンパイルする場合は、プログラムを実行するプロセッサやプラットフォームのタイプごとに異なる実行可能ファイルをコンパイルする必要があります(たとえば、Windows x86用、Windows x64用、Linux x64用など)。に)。さらに、コードが完全に標準に準拠していて、プラットフォーム固有の関数やライブラリを使用していないのでない限り、実際には複数のコードベースを作成して維持する必要があります。

あなたのソースコードが解釈されるならば、あなたはそれを一度だけ書く必要があります、そしてそれはどんなプラットフォームの適切なインタプリタによっても解釈され実行されることができます!それはポータブルです!インタプリタ自体は、が特定のプラットフォーム用に書かれコンパイルされた実行可能プログラムであることに注意してください。

コンパイルされたコードの利点は、エンドユーザーからソースコードを非表示にする(これは知的財産かもしれません)オリジナルの人間が読めるソースコードを展開する代わりに、あいまいなバイナリ実行可能ファイルを展開します。

11
Niko Bellic

コンパイラとインタプリタは同じ仕事をします。プログラミング言語を他のpgoramming言語に、通常はハードウェアに近いところに翻訳し、しばしば実行可能なマシンコードを指示します。

伝統的に、「コンパイルされた」とは、この翻訳がすべて一度に行われ、開発者によって行われ、その結果として得られる実行ファイルがユーザーに配布されることを意味します。純粋な例:C++。コンパイルは通常かなり時間がかかり、結果として得られる実行可能ファイルがより速く実行されるように高価な最適化の多くを試みます。エンドユーザーは自分でものをコンパイルするためのツールや知識を持っておらず、実行可能ファイルはさまざまなハードウェア上で実行する必要があるため、ハードウェア固有の最適化を多数行うことはできません。開発中、個別のコンパイル手順はより長いフィードバックサイクルを意味します。

伝統的に、「解釈された」とは、ユーザーがプログラムを実行したいときに、「その場で」翻訳が行われることを意味します。純粋な例:Vanilla PHP。素朴なインタプリタは、実行するたびにすべてのコードを解析して変換する必要があるため、非常に遅くなります。実行にかかる時間よりも長い時間がかかるため、複雑でコストのかかる最適化を行うことはできません。しかし、それはそれが動作するハードウェアの機能を十分に活用することができます。個別のコンパイル手順がないため、開発中のフィードバック時間が短縮されます。

しかし、今日では「コンパイル対解釈」は白黒の問題ではなく、中間に色合いがあります。素朴で単純な通訳はほとんど絶滅しています。多くの言語は、高レベルのコードがプラットフォームに依存しないバイトコード(これは解釈するのがはるかに速い)に変換される2段階のプロセスを使用します。それから、プログラムの実行ごとにせいぜい一回だけコードをコンパイルし、時には結果をキャッシュに入れ、そしてめったに実行されないコードを賢く解釈することを決心し、そして頻繁に実行するコードに対して強力な最適化を行う「ジャストインタイムコンパイラ」があります。開発中、デバッガは伝統的にコンパイルされた言語であっても実行中のプログラム内のコードを切り替えることができます。

7

まず、明確化、JavaはC++のように完全に静的にコンパイルされリンクされているわけではありません。これはバイトコードにコンパイルされ、それがJVMによって解釈されます。 JVMはネイティブの機械語にジャストインタイムでコンパイルすることができますが、行う必要はありません。

もっと端的に言えば、私は対話性が主な実用上の違いであると思います。すべてが解釈されるので、あなたはコードの小さな抜粋を取り、環境の現在の状態に対してそれを解析しそして実行することができます。したがって、すでに変数を初期化するコードを実行したことがある場合は、その変数などにアクセスできます。これは、機能的なスタイルなどに適しています。

しかし、特に大量の参照や文脈を持つ大規模なシステムがある場合、解釈には多大な費用がかかります。定義上、まったく同じコードを2回解釈して最適化する必要があるため、無駄になります(ただし、ほとんどのランタイムではキャッシュと最適化が行われています)。それでも、あなたはランタイムコストを払い、多くの場合ランタイム環境を必要とします。現時点ではパフォーマンスが十分に対話的ではないため、複雑なプロシージャー間の最適化も見られません。

したがって、それほど変わらない大規模なシステムの場合、および特定の言語の場合は、すべてをプリコンパイルおよびプリリンクして、できる限りすべての最適化を行うことが理にかなっています。これは、ターゲットマシン用にすでに最適化されている非常に無駄のないランタイムになります。

実行可能ファイルを生成することに関しては、それはそれとはほとんど関係がない、私見。多くの場合、コンパイル済み言語から実行可能ファイルを作成できます。ただし、インタプリタとランタイムがすでに実行可能ファイルにパッケージ化されていてユーザから隠されている場合を除き、インタプリタ言語から実行ファイルを作成することもできます。これはつまり、一般的にはまだランタイムコストを支払うことを意味します(ただし、言語によっては、すべてをツリー実行可能ファイルに変換する方法があると思います)。

私は、すべての言語をインタラクティブにすることができるとは思わない。 Cなどの特定の言語は、マシンとリンク構造全体に密接に関係しているため、意味のある本格的な対話型バージョンを構築できるかどうかはわかりません。

4
Uri

Python Book©2015 Imagine Publishing Ltdは、10ページで次のように述べられている次のヒントによって違いを区別しています。

Pythonなどのインタプリタ言語は、ソースコードがマシンコードに変換されてからプログラムが実行されるたびに実行される言語です。これは、ソースコードが1回しかマシンコードに変換されないCのようなコンパイルされた言語とは異なります。結果のマシンコードはプログラムが実行されるたびに実行されます。

2

違いは言語定義自体にあるため、実用的な答えを出すことはかなり困難です。コンパイルされた言語ごとにインタプリタを構築することは可能ですが、インタプリタ言語ごとにコンパイラを構築することは不可能です。それは言語の正式な定義について非常に重要です。だから理論情報学は大学では誰も好きではない。

2
Steven Mohr

コンパイルは、コンパイルされたプログラミング言語で書かれたコードから実行可能プログラムを作成するプロセスです。コンパイルすることで、作成に使用したプログラミングソフトウェアを使用せずに、コンピュータでプログラムを実行および理解することができます。プログラムがコンパイルされるとき、それはしばしばIBMコンパチブルコンピュータと共に動作する特定のプラットフォーム(例えばIBMプラットフォーム)のためにコンパイルされるが、他のプラットフォーム(例えばアップルプラットフォーム)のためにはコンパイルされない。最初のコンパイラは、Harvard Mark Iコンピュータの開発中にGrace Hopperによって開発されました。今日では、ほとんどの高級言語には独自のコンパイラが含まれているか、プログラムのコンパイルに使用できるツールキットが用意されています。 Javaで使用されるコンパイラの好例はEclipseです。CおよびC++で使用されるコンパイラの例はgccコマンドです。プログラムの大きさに応じて、コンパイルに数秒または数分かかります。コンパイル中にエラーが発生しなかった場合は、実行可能ファイルが作成されます。この情報を確認してください。

1
salehvm

違い

通訳者:

1)プロセス:インタプリタはプログラムから結果を出す。 (プログラムの実行時にプログラムをマシンコードに変換します)一方、インタプリタプログラムでは、ソースコードは通常プログラムです。このタイプのプログラム(多くの場合スクリプトと呼ばれる)には、プログラム内のコマンドを解析して実行するインタープリタが必要です。 Unixシェル(sh、csh、kshなど)などの一部のインタプリタは各コマンドを読み取ってすぐに実行しますが、Perlなどのインタプリタは対応する機械語命令を送信する前にスクリプト全体を分析します。インタプリタ言語の他の例には、JavaScriptとPythonがあります。

2)開発(編集および実行)が速い。

3)各ステートメントは実行されるたびに機械語に変換されなければならないため、実行が遅くなります(これが何千回も実行されたループの意味を考えてください)。

4)あなたのソースコードが解釈されるならば、あなたはそれを一度だけ書く必要があります、そしてそれはどんなプラットフォームの適切なインタプリタによっても解釈され実行されることができます!

5)インタプリタを使うことの不利な点は、それがエンドユーザからソースコードを隠さないことです。

6)最初のエラーが発生するまでプログラムの翻訳を続けます。この場合、エラーは停止します。したがって、デバッグは簡単です。

コンパイラ:

1)処理:(プログラムが実行される前にプログラムを機械語に変換する)コンパイラがアセンブリ言語で書かれたプログラムを生成する間。次に、アーキテクチャーのアセンブラーは、結果のプログラムをバイナリーコードに変換します。アセンブリ言語は、アーキテクチャによってコンピュータごとに異なります。その結果、コンパイルされたプログラムは、それらがコンパイルされたコンピュータと同じアーキテクチャを持つコンピュータでしか実行できません。コンパイルされたプログラムは人間が読めるものではありませんが、その代わりにアーキテクチャ固有の機械語です。コンパイル済みプログラムを作成するにはいくつかのステップが必要です。まず、プログラマは、開発ツールや単純なテキストエディタを使用して、選択したコンピュータ言語でソースコードを書きます。プログラムが複雑な場合は、その一部が複数のファイルに分散している可能性があります。次にプログラマはプログラムをコンパイルし、モジュールをソートしてリンクし、それらすべてをコンピュータが理解できるマシンコードに変換します。異なる種類のコンピュータは互いの機械語を話さないため、コンパイルされたプログラムはそれが設計されたプラットフォーム上でしか動作しません。たとえば、HP-UX用に書かれたプログラムは通常、Mac OSコンピュータやSolarisを実行しているコンピュータでは動作しません。

2)開発が遅い(編集、コンパイル、リンク、実行)。コンパイル/リンクの手順は大変な時間がかかります。

3)実行が速い。プログラム全体はすでにネイティブのマシンコードで書かれていました。

4)コンパイルされたプログラムはそれが設計されたプラットフォーム上でのみ動作します。持ち運びできない

5)コンパイル済みコードの利点は、元の人間が読めるソースコードを展開する代わりに、あいまいなバイナリ実行可能ファイルを展開するため、エンドユーザーからソースコードが隠されることです(知的財産かもしれません)。 6)プログラム全体をスキャンした後にのみエラーメッセージを生成します。そのため、デバッグは比較的困難です。

出典:* https://kb.iu.edu/d/agsz *この投稿のさまざまな答え

0
abc123