2012年6月4日月曜日

コンパイルとリンク

コンパイル

機械が実行できる機械語の命令を人間が読み易い言葉にほぼ一対一で直して記述していくアセンブラという言語があります。
C++や、その他多くのプログラミング言語は、アセンブラよりはもっとおおまかにどのような文を書いたら機械にどのような処理をさせるかその規約を定めたものだと言えます。
アセンブラの場合は機械へ与える命令の数だけ文を書かないといけません。しかしその他のプログラミング言語はよくやる処理を簡単な文で記述できるようにしてあるので、ひとつの文を書けば、大抵、複数の機械語が生産されます。
どのようなプログラミング言語を使うにしろ、最終的にはそれが機械語の命令に翻訳される必要があります。


人間が読めるC++の例
int x, y, z;
x = 2;
y = 3;
z = x * y;

機械が読める機械語のコードの例
10001001
00111100
01000000
・・・実は適当に書きましたが、純粋な機械語は0と1の配列になっているので、普通の人は解読できません。



プログラミング言語のコードから機械語を生産(翻訳)する事をコンパイルと言います。また、それを行う装置をコンパイラと呼びます。
C++のどういう文をコンパイルするとどういう機械語に翻訳されるかはコンパイラを作る人やメーカーの裁量に任されますが、少なくともC++が規定、想定する処理が行えるような機械語の命令に翻訳されない限りはC++のコンパイラとしては不備があると見なされます。(ただし、あえて特殊な使い方が出来るようにコンパイラの提供者が独自の仕様を盛り込むことはあります。)

コンパイルを行う機能はVC++(Visual C++ とかVisual Studio)等のプログラミングの開発環境に備わっています。

なお、コンパイルが終わって0と1の2進数で表現されているバイナリファイルのコードをオブジェクトコードと言い、そのファイルをオブジェクトファイルと言います。
一方、C++の様な人間が読める状態のテキストファイルのプログラムコードはソースコードと言い、そのファイルをソースファイルと呼びます。


リンク

プログラムの作成はコンパイルで終わりではありません。大抵のプログラムは独立した存在ではなく、他の多くのプログラムから機能を得て成立しています。自分でプログラムを複数のファイルに分けて書くこともありますし、CやC++の標準ライブラリの様にライブラリと呼ばれるものを使う事もあります。

プログラマーは自分が書くC++のソースコードの冒頭に

#include "ヘッダファイルの名前"
という様な記述をします。これでファイルをインクルード(内包)出来ます。
例えばウインドウズの一般的な機能を使いたいなら
#include <windows.h>
を書きます。
#includeという既述は、その先に書いたファイルの内容をこの場所に持って来るという役割を持ちます。この例で言えば
#include <windows.h>
の一行を消して替りにwindows.hファイルの中身をこの場所に丸々コピーしても同じ事です。

多くのファイルからインクルードされる事を想定して作られたファイルには.hの拡張子を付けてその意図を示してあります。この.hが付いたファイルはヘッダファイルと呼ばれます。
ヘッダファイルの中には関数の宣言が書かれているため、ライブラリのユーザーはその関数を自分のプログラムで呼び出せるのです。

コンパイルが済んだ複数のオブジェクトファイルを連結させる作業をリンクといいます。 コンパイルをするのはコンパイラの役割でしたが、リンクをするシステムはリンカと呼びます。コンパイルやリンクを経て最終的に出来上がるファイルは実行ファイルと呼ばれます。我々が良く目にする一般的なアプリケーション、つまりアイコンの絵があって拡張子が.exeになっている奴が実行ファイルです。ご存知の様にこれをダブルクリックするとプログラムが開始します。

ソースファイルからコンパイルとリンクを経て実行ファイルを作る事を纏めてビルドと呼び、設定さえ済んでいればVC++等の統合開発環境からボタン一つで行えます。VC++ではF7キーでビルド、F5キーはビルした上にさらに出来たプログラムの実行まで行えます。

↓プログラミングの大まかな手順はこんな感じになります。

ちなみにライブラリは静的なライブラリと動的なライブラリ(ダイナミックリンクライブラリ)の2種類があり、動的な方は実行ファイルが実行されるまで実際の連結は行いません。
ここの説明がわかり易かったので引用しておきます。
-----------------
ライブラリには大きく2種類存在します。1つは「スタティックライブラリ」。これはプログラムに組み込んで最終的に実行ファイル形式内にソースを固定してしまうライブラリです。実行ファイルを作成してしまったら変更が出来ないので「スタティック(静的)」と名付けられています。拡張子はlibです。もう1つは「ダイナミックリンクライブラリ」。これは実行ファイルの中にソースを含めず、実行中にライブラリを展開してその実行バイナリコードを使用できるライブラリです。実行ファイルを作成した後もライブラリ自体の変更が可能で、それにより実行ファイルの機能を変えたり拡張できたりするので「ダイナミック(動的)」と名付けられています。拡張子はdllです。

どちらのライブラリにも一長一短があります。libの方はプログラムソースとして完全に固定してしまうので、完全に動くプログラムを保証します。しかし、作成された実行ファイルは変更ができないので、バージョンアップをするときには実行ファイルごとコンパイルしなおさなければなりません。dllの方は実行ファイルが外部ソースとしてアクセスするので、dllを丸ごと取り替えてしまえば異なる動作をさせることが可能になります。これはソフトのバージョンアップやパッチ修正を容易にします。しかし、dllによるアクセスは一般に手続きが多く、またdllが無い場合や壊れている場合に実行ファイルの動作保証ができなくなります。また、実行ファイルは完全にdllを意識した書き方になります。

-----------------

コンパイラ先生

今時のコンパイラやIDE(統合開発環境)は、コンパイル時にプログラマーが書いたソースコードに間違や不備があると、エラーを報告したり警告をしてくれます。そして具体的にソースコードのどこが誤りだったかを指摘してくれるでしょう。コンパイラにしてみれは、機械が実行できる正しい機械語のコードを作成するという使命がある訳です。それなのにプログラマーが変なコードを書くと、それをどの様に機械語に訳せば良いかが分からないので、エラーを出して書き直しを求めて来るという訳です。
VC++ではエラーや警告の文をダブルクリックするとソースコード上の問題の箇所に飛ぶ事が出来ます。
また、エラーとまで言えなくても、文法上曖昧な箇所や、解釈は可能だけど、そういう書き方は普通しないよね・・・という場所を警告してくれます。
こういったコンパイラーが出す報告は初めは読みにくかったりするのですが、多くの症例をこなす内に、理解できるようになるかと思います。
コンパイラはソースコードの翻訳者であると共に、我々にC++を教える文法の先生でもある気がします。

・・・最近はコンパイルしなくてもエディタ上に誤った文法を書いた時点で教えてくれたりもするので尚更便利になりました。

0 件のコメント: