2017-01-24 21 views
1

私は最近、コンパイラデザインのドラゴンブックを読んだ。コンパイラには、機械に依存しないコードを生成するフェーズの1つとして、中間コード生成が含まれていることが記載されています。それではCはJavaのようなプラットフォームに依存しない言語として開発されなかったのはなぜですか?Cがプラットフォームに依存しない言語になっていないのはなぜですか?

+7

そのデザイナーは「Javaのようなプラットフォームに依存しない言語」を探していませんでした。彼らは、機械に近い、アセンブラよりも高いレベルで便利なものを求めていましたが、アセンブラに匹敵する効率を持ち、1970年代のコンパイラテクノロジを使用してコンパクトなコードを書き込めるようにしました。シンプルなプロジェクト。 –

+0

プラットフォームの依存性の問題は後で確認されましたか? – Curiosity101

+2

"machine independent code"はおそらく "マシンに依存しない内部表現"を意味しますが、依然としてその表現にエンコードされたマシン依存要素が存在します。そう言って、あなたが何を求めているのかがはっきりしない。 – davmac

答えて

9

は、以下のプロセスである:

  1. 中間機種に依存しないバイトコード形式にソースコードをコンパイルIR翻訳
  2. そのIRに最適化を実行し、解析し、ターゲットプラットフォームの実際のマシンコードへ

追加のシステムをサポートしたい場合、新しいcを追加するだけですステップ1とステップ2に触れることなくステップ3のodeジェネレータを起動します。

すべての一般的なCコンパイラはこのように動作します。だからあなたの質問が「なぜCコンパイラがドラゴン・ブックの説明をしていないのですか?」という答えは、「彼らはしています。

ここでJavaに言及しました。 Javaコンパイラの機能は、次のとおりです。

  1. JavaコードをJavaバイトコードにコンパイルします。 Javaコンパイラに関する限り、これは中間形式ではなく、実際のターゲット言語です。
  2. エンド

今、あなたはバイトのボード線図を解釈し、および/またはそれをJITコンパイルし、JVMを必要とする。このバイトコードを実行します。最適化と分析は、通常、JITコンパイル中に行われます。これはDragon Bookに記載されているプロセスではありません。

これは、言語実装者の観点からは、新しいターゲットシステムを非常にサポートする努力を変えるものではありません。コンパイラを変更する必要はなく、代わりにJVMを変更する必要があります。新しいバックエンドをjavacコンパイラに追加する代わりに、新しいバックエンドをJITコンパイラに追加します。努力は基本的に同じままです。

主な違いは、Javaプログラマの場合です。ターゲットプラットフォームごとにプログラムをコンパイルし、プラットフォームごとにパッケージを配布するのではなく、コードを一度コンパイルしてすべての人に配布できるようになりました。あなたのコードを実行している人は、パッケージを使用できるようにJVMをインストールする必要があります。基本的にプログラマからエンドユーザに作業を移しましたが、JVMをインストールすることは、あなたが実行したいプログラム)。

"一度書いて、どこでもコンパイル"ではなく、 "一度コンパイルするとどこでも実行"できるようになりました。

なぜCはJavaと同じことをしませんでしたか?パフォーマンス。バイトコードの解釈が遅く(コンパイルされたコードの実行と比較して)、JITコンパイルは起動時間の増加につながります。

+0

私はこれが答えだと思う、OPのようなマシンの独立したIRについて混乱しているように見える!=プラットフォームに依存しない言語。 –

+0

@ArturKink、マシンに依存しないIRとして(Cコンパイラの文脈では)そのようなことは言及されていません。 GIMPLEとLLVM IRの両方は、プラットフォームに大きく依存しています。 –

1

短い答え:その時点では実現できませんでした。

長い答え:Javaプラットフォームは言語+仮想マシンであり、JavaコードはByteCodeと呼ばれるものにコンパイルされ、仮想マシンはこのバイトコード(アセンブリ言語に似ています)を取得し、関連する実行時のコマンド。ローカルマシンが理解できるマシン命令を意味します。

すべてのアーキテクチャには独自の命令セットがあります。つまり、ARMアーキテクチャは、たとえばx86アーキテクチャ用にコンパイルされたコードを理解できません。

C言語では、Cコードはマシン命令に直接コンパイルされ、これらの命令はローカルマシンによって実行されます。 Javaのような動作をさせるためには、C言語を読み込み、実行時にマシンコードに変換する何らかの解釈プログラムが必要ですが、これは安価なタスクではなく、時間のコンピュータにはあまりにも多くのことでした(cは1972)はもちろん、これを実装する別の方法は、ユーザがあなたのプログラムを使用する前にコンパイルするようにすることです。これはうまくいくかもしれませんが、ソースコードをクライアントに見せてしまうことになります。うまくいけば、それは少し物事を明確にします。

0

ほかに(実際には、これが大きくプラットフォーム/ ABI-定義されているが、厳密にはなくてもかまいません)のもの実装定義の数を残してから、C は、主に、プラットフォームに依存しない言語です。実際に、適切なランタイム環境を持つ任意のマシンプラットフォームで実行できる形式で出力を生成するCの実装(emscriptenなど)があります。 C言語で記述されたソフトウェアが、実装の定義した(あるいは悪い、定義されていない)言語の側面について仮定すると、実装/機械によっては動作しない可能性がありますが、API /環境/ライブラリ前提条件(POSIX、Windows、またはglibcismsを前提とするような)は、移植言語そのものに関する移植性のない仮定を行うよりも重要です。

1

Cはもともと「書き込み一度、コンパイル・アシスタント」言語として設計されており、当時は普遍的な言語に近いほどコンパイルされていました。

プロセッサーとアーキテクチャーは根本的に異なり、リソースは非常に小さく、ユニバーサル仮想マシン(Javaのように)のアイデアは不可能でした。

コンパイラを介して単一のコードベースを実行できるというアイデアは、どのターゲットプラットフォームでも同じソフトウェアを使用することはかなり信じられませんでした。

+3

Pコードの存在(例えば)は、おそらくナイーブな時代の概念の信憑性に矛盾しますか? – rici

2

Cは、最初は特定のマシンを含む特定のユースケース用に設計されました。プラットフォームに依存しない仮想マシンによって実装された言語BCPLに基づいていましたが、Cの目的は、オペレーティングシステムなどの低レベルのコードを書くことができることでした。ターゲットマシンの特定の機能、特に個々のバイトを直接アドレス指定する機能を利用できるようになります。対照的に、BCPLの基盤となるアーキテクチャは、断言的に言葉志向です。

Bell LabsがUnixオペレーティングシステムを新しい言語ですばやく再実装できたという事実は、確かにその人気に貢献しました。 (少なくとも、それは私が最初にそれを学んだ理由です。)言語の広範な普及を可能にするために、コンパイラのバージョンは、Dragon Machineの初期世代の仮想マシンコードを使用して、ターゲットマシンのコードを生成するために使用されています。このポータブルCコンパイラは長年にわたりリファレンス実装であり、引き続き利用可能でした。

Cと並んでいる他の言語、特にPascalは、プラットフォームに依存しない仮想マシンをターゲットとした戦術も使用していました。これは、仮想マシンコードを「Pコード」と呼ぶのがかつてのことでした。ターゲットアーキテクチャ

GCCは仮想マシンをそのまま使用しませんが、LCCレベルのマシンに依存しない内部表現を生成することから始まります。コンパイラを新しいアーキテクチャに移植する作業が簡単になります。もちろん、ClangコンパイラはLLVM(低レベル仮想マシン)コードを生成します。このコードは、さまざまな具体的なマシンコードに変換するか、直接解釈することができます。ドラゴンブックが記述されて何