
C言語入門|コンパイラとリンカの役割
プログラムは一気に完成しているわけではない
C言語のプログラムは、ソースコードを書いてコンパイルすると、すぐに実行できるファイルができあがるように見えます。
しかし実際には、その裏側で複数の工程が順番に進められています。
その工程を支えているのが、
- コンパイラ
- リンカ
という、役割の異なるソフトウェアです。
ここでは、プリプロセッサの後に何が起きているのか を、順を追って見ていきましょう。

プログラムが完成するまでの全体像
C言語のプログラムは、次の流れで完成します。
まず、私たちが書いたソースコードは、プリプロセッサによって前処理されます。
この段階で、コメントの削除や include の展開、マクロの置換が行われます。
次に、その前処理済みのソースコードが コンパイラ に渡されます。
コンパイラは、C言語の文法として正しいかを確認し、問題がなければ CPU が理解できるマシン語へと翻訳します。
この結果として作られるのが オブジェクトファイル です。
ただし、オブジェクトファイルはまだ完成品ではありません。
printf のような標準関数や、別ファイルで定義された関数の中身は含まれていないため、そのままでは実行できません。
そこで最後に登場するのが リンカ です。
リンカは、複数のオブジェクトファイルやライブラリファイルを結合し、必要な関数の実体をすべてそろえたうえで、最終的な 実行可能ファイル を作成します。
このように、
コンパイルとリンクは別の工程 として行われているのです。
コンパイラの役割とは何か
プリプロセッサを通過したソースコードは、まだ人間にも読めるテキストです。
しかし、CPU が理解できるのはマシン語だけでしたね。
このギャップを埋めるのがコンパイラです。
コンパイラが行う2つの仕事
コンパイラの仕事は、次の2つに整理できます。
| 項目 | 内容 |
|---|---|
| 文法チェック | C言語のルールに沿って書かれているか確認する。 |
| 翻訳 | ソースコードをマシン語へ変換する。 |
この結果として生成されるのが オブジェクトファイル です。
オブジェクトファイルの正体
オブジェクトファイルは、
- マシン語に変換されている。
- 文法エラーは存在しない。
という状態ですが、
- 単体では実行できない。
という特徴を持っています。
理由は、他のファイルに定義された関数や、標準ライブラリの関数の実体がまだ含まれていないからです。
コンパイルが通っても実行できない理由
たとえば、printf を使ったプログラムを考えてみましょう。
stdio.h をインクルードしているため、printf を使うことはできます。
しかし、インクルードによって取り込まれているのは printf の宣言 だけです。
printf が実際にどのような処理を行う関数なのか、その中身は 別の場所 にあります。
その不足分を補う工程が必要になります。
リンカの役割とは何か
リンカは、未完成の部品であるオブジェクトファイルを集めて、
1つの完成品に仕上げる役割を担います。
リンカの仕事
リンカの仕事をまとめると、次のようになります。
| 項目 | 内容 |
|---|---|
| 結合 | 複数のオブジェクトファイルをまとめる。 |
| 解決 | 関数や変数の参照先を確定させる。 |
| 生成 | 実行可能ファイルを作成する。 |
このとき、必ず main 関数を含むオブジェクトファイル が必要になります。
標準ライブラリと libc の関係
printf をはじめとする標準関数の実体は、
libc というライブラリにまとめられています。
この libc もリンカによって結合される対象の1つです。
C言語の開発では、ほぼすべてのプログラムが libc を利用するため、通常は特別な指定をしなくても自動的にリンクされます。
ライブラリファイルの種類
ライブラリには、用途に応じていくつかの形式があります。
| 拡張子 | 内容 |
|---|---|
| .o / .obj | 単体のオブジェクトファイル |
| .a / .lib | 静的ライブラリ |
| .so / .dll | 動的リンクライブラリ |
動的リンクライブラリは、実行時に読み込まれるため、実行ファイルのサイズを小さくできるという特徴があります。
コンパイラとリンカの役割まとめ
最後に、役割分担を整理しておきましょう。
| 担当 | 役割 |
|---|---|
| コンパイラ | 文法チェックとマシン語への翻訳 |
| リンカ | 部品の結合と実行可能ファイルの完成 |
この分業構造があるからこそ、
- ファイル分割
- 複数人開発
- ライブラリの再利用
が可能になっています。
