ソースコード全体を一括して機械語に翻訳し、実行ファイルを生成するプログラム。
コンパイラとは、ソースコード全体を一括して機械語に翻訳し、実行ファイルを生成するプログラムです。プログラムを動かす前に「全部まとめて翻訳しておく」のが最大の特徴です。
身近な例で考えると、本を1冊まるごと翻訳して出版するのに似ています。最初に全文を訳して翻訳版の本(実行ファイル)を刷っておけば、読者は訳者を待たずにすぐ読めます。翻訳に手間はかかりますが、一度作れば何度でもスムーズに読めるわけです。
上のツールで▶ボタンを押すと、「x = 1 + 2」という小さなコードが、字句解析から実行ファイル完成まで各段階を順に通っていく様子を確認できます。
コンパイラは、ソースコードを次の段階を順に通して機械語へ変換します。
・字句解析:文字の並びを意味の最小単位(トークン)に分解する
・構文解析:トークンが文法的に正しいか調べ、構文木に組み立てる
・意味解析:型や変数の整合性など、意味として正しいかを確認する
・最適化:結果を変えずに処理を速く・小さくする工夫を施す
・コード生成:仕上げに機械語の命令列を作り出す
これは工場の生産ラインに似ています。素材(ソースコード)が、切り分け→組み立て→検査→改良→仕上げ、と各工程を順に流れていき、最後に製品(実行ファイル)が完成するイメージです。前の工程が終わらないと次へ進めない点も生産ラインと同じです。
とくに最適化では、「1 + 2」のように実行前から答えが分かる計算をあらかじめ「3」に計算しておく(定数畳み込み)など、賢い工夫が行われます。上のツールで各段階の中身がどう変わるかを順に追ってみてください。
同じ「高級言語の変換役」でも、いつ翻訳するかが決定的に違います。コンパイラは事前に一括翻訳して実行ファイルを作るので、実行時には翻訳が不要で動作が速いです。一方インタプリタは1行ずつ解釈実行するため、起動が速く移植性(=別の環境でも動かしやすい性質)が高い反面、毎回解釈する分だけ実行は遅くなります。
| 項目 | コンパイラ | インタプリタ |
|---|---|---|
| 翻訳のしかた | 事前に一括翻訳 | 1行ずつ解釈実行 |
| 実行ファイル | 作る | 作らない |
| 実行速度 | 速い | 遅め |
| 得意なこと | 実行性能 | 起動の速さ・移植性 |
料理にたとえると、コンパイラはレシピを全部読んで作り置きしておく方式、インタプリタはレシピを1行読んでは作る方式です。作り置きは食べるときが速く、その場調理は手軽に始められる、と覚えると整理しやすいです。
コンパイラの一括翻訳には大きなメリットが2つあります。
・実行が速い:実行時には翻訳済みの機械語を動かすだけなので、毎回解釈する手間がない
・エラーを事前にまとめて発見できる:コンパイル時にソース全体をチェックするため、実行する前に間違いを見つけられる
一方でデメリットもあります。
・最初のコンパイルに時間がかかる:大きなプログラムは翻訳だけで数分かかることもある
・環境に依存した実行ファイルができる:Windowsで作った実行ファイルはMacではそのまま動かないことが多い。実行ファイルはOSやCPUの種類に合わせて作られるため、別の環境では再度コンパイルが必要になる
なぜ実行が速いのか、もう少し掘り下げると——コンピュータが直接理解できるのは機械語(=CPUが実行できる命令の並び)だけです。コンパイラはすでに機械語に変換済みのファイルを作るので、実行時は「命令どおりに動くだけ」。インタプリタのように毎回「どういう意味か?」と解釈し直す必要がないぶん、速く動けるのです。
コンパイラと似た名前の道具がいくつかありますが、役割が違います。
・コンパイラ:人間が書いた高級言語(C言語・Javaなど)を機械語に一括翻訳する
・アセンブラ:アセンブリ言語(=機械語とほぼ1対1に対応した低レベルな言語)を機械語に変換する。コンパイラより翻訳対象のレベルが低い
・リンカ:コンパイラが作った目的ファイル(=まだ完成していない機械語の断片)を複数結合して、1つの実行ファイルを完成させる
なぜリンカが必要か。大きなプログラムは複数のソースファイルに分けて書かれることが多く、コンパイラはファイルごとに目的ファイルを作ります。バラバラの部品をひとつにまとめて初めて動く実行ファイルになるので、それをつなぐ「接着剤」がリンカです。身近な例では、工場で作られた部品(目的ファイル)を組み立てて製品(実行ファイル)に仕上げる最終工程がリンカの仕事です。