第3回
ソースの入力から完成まで

コンパイラとリンカ

ソースコードを機械語に変換することを、一般にコンパイル(compile)といいます。が、OS上で動作するプログラム──実行形式ファイルを生成するには、コンパイルに続いてリンク(link)という処理が必要になります。

コンパイラ型とインタープリタ型

プログラミング言語にはインタープリタ型とコンパイラ型があって……ということは、みなさんご存じだと思います。まぁ、とりあえず簡単に説明しておきましょう。

インタープリタ(interpreter)の原義は「通訳」のことで、入力したソースコードを1行または1命令単位で、逐次機械語に変換し実行していく仕組みです。代表格は(Visualでない方の)BASICでしょう ※1

コンパイラ(compiler)の原義は「翻訳者」のことで、入力したソースを一括して機械語に変換します。このコラムで取り上げているCはコンパイラ型の言語です ※2

一般に、インタープリタ型の言語は実行速度が遅いかわりにエラーの訂正などカット&トライ方式の開発が楽で、コンパイラ型の言語は実行速度が速いかわりに修正が面倒――という特徴があります。

BASICに限らず、インタープリタ型の言語にはコンパイラが存在するものも多くあります
その昔、インタープリタ型のC処理系が存在していました。学習用ということで、実行してはエラーを確認して修正する――というインターフェイスが便利でした

中間言語とは?

今、「コンパイラ型の言語は、入力したソースを一括して機械語に変換する」と書きました。が、実はこの表現は正しくありません。ソースコードは人間の理解できる言語ですが、コンパイラがそれをいきなりCPUの理解できる機械語に変換するわけではありません。

コンパイラは、ソースコードをその処理系独自の中間言語に変換してファイルを出力します。このファイルをオブジェクトファイルと呼びます ※3

実は中間言語という呼び名はあまり一般的ではありません。が、オブジェクトファイルあるいはオブジェクトコードという名称はC++などのオブジェクト指向プログラミングと混同されやすいため、『ソースコードと最終的な機械語との間に位置する言語』という意味で中間言語という名称を用いることにします。

日本語ではソースを『原始プログラム』、オブジェクトを『目的プログラム』と呼びます

リンカの役割

Cでは、ソースをコンパイルして生成された中間言語ファイルを、ライブラリとしてまとめることができます。

ライブラリに収録された中間言語ファイルも、ソースをコンパイルして生成された中間言語ファイルも、同じように扱われます。これらはリンカ(linker)というプログラムによって1つに結合され、最終的な実行形式ファイルになります。

実行形式ファイルには、その他にスタートアップ・ルーチンと呼ばれるプログラムも結合されます。それもリンカの仕事です。スタートアップ・ルーチンは、OSのシェルによってメモリに読み込まれて実行される最初の処理部分で、どのようなプログラムにも共通した初期化が行われます。

初期化を終えると、スタートアップ・ルーチンはmain関数を呼び出し、プログラム独自の処理が開始されます。その中で、例えばprintf関数が呼び出されていれば、リンカによって結合されたライブラリ内のprintf関数が実行されます。