Gather

description

-My Recommended Tools for Tumblr-

*Tombloo(Firefox Extension) for quick and easy posting

*Greasemonkey(Firefox Extension) with AutoPagerize for automating loading next page and inserting into current page

+Trac Tumblr for search Tumblr and get RSS feed

Aug 06

“Quote”

[ コンパイルのしくみ ]

cc は,ソースファイルをコンパイルして実行ファイル a.out を生成するコマンドです.cc が行なうコンパイル処理には,実際には次に挙げる複数の処理が含まれています.

  1. 前処理 (cpp)
  2. コンパイル (ccom)
  3. アセンブル (as)
  4. リンク (ls)

括弧内に記したものは,それぞれの処理を受け持つコマンドです.cc は,実際にはこれらのコマンドを次々と呼び出すことによってコンパイル処理を行ないます.この様子を Fig. 1-1 に示します.

図中,コマンドとコマンドの間に記されたものは,直前のコマンドが生成する中間ファイルです.cc による処理が終了した時点でこれらの中間ファイルは消去されます(あるいはコマンド間で直接データが受け渡され,中間ファイルは作られない場合もあります)が,cc にオプションを設定すれば,各々の中間ファイルを得ることができます.次に,個々のコマンドについて説明します.

 1. 前処理

コマンド cpp はプリプロセッサと呼ばれます.例えばソースファイル sample.c の場合,その第1行:

#include <stdio.h>

はファイル stdio.h をこの場所に取り込むことを cpp に指示します(このようにプログラムの初めの部分で取り込むファイルのことを,ヘッダファイルまたはインクルードファイルと呼びます).ヘッダファイル stdio.h はディレクトリ /usr/include 以下にあります.cpp は,#include <…> という行(include文と呼びます)を見つけると,/usr/include 以下に < > で囲まれたファイル名のファイルを探し,もしあれば,そのファイルを include文と置き換えます(もしなければエラーになります).

ヘッダファイル stdio.h には sample.c 内で引用している関数 printf() の定義などが含まれています.詳しくは後の回で説明しますが,stdio.h はほとんどのプログラムにおいて取り込む必要があります.

プリプロセッサは,ファイルの取り込みの他にマクロの展開コメントの除去などを行ないます.

マクロの展開とは,マクロ名定義された文字列に置換する操作です.プログラマーは,例えば

#define MAX 100

という行(define文と呼びます)をプログラムの最初の部分に書くことができます.このとき cpp はプログラム中でマクロ名 “MAX” を見つける度に,そのマクロ名を定義された文字列 “100” に置き換えてゆきます.

コメントとは,/* と*/ で囲まれた文字列です.コメントにはC言語の文法に関わりなく自由に注釈を書くことができます.cpp はすべてのコメントを除去します.ただし,コメントの入れ子(/*…*/ の中に /*…*/ があること)は禁止されています.

 2. コンパイル

コマンド ccom はコンパイラの本体です.ccom はプリプロセッサの出力を解析し,アセンブラプログラムを生成します.ここにアセンブラプログラムとは,アセンブリ言語(機械語と1対1に対応した,最も低水準な言語)によって表現されたプログラムのことです.アセンブラプログラムはソースプログラムの一種です.したがって,プログラマーが作成/編集することができます.

 3. アセンブル

コマンド as はアセンブラと呼ばれます.アセンブラは アセンブラプログラムを読み込んでオブジェクトプログラムを生成します.ここにオブジェクトプログラムとは,機械語(文字によって表現できない1と0からなるコード)によって表現されたプログラムのことです.コンパイラの目的(オブジェクト)がソースプログラムから機械語によるプログラムを生成することなので,オブジェクトプログラム と呼ばれます.なお,オブジェクトプログラムを納めたファイルをオブジェクトファイルと呼びます.

 4. リンク

コマンド ld はリンカと呼ばれます.リンカの役目はオブジェクトプログラムどうしを結合(リンク)し,実行ファイルを生成することです.一般にC言語のプログラムでは,関数によってひとまとまりの処理を表わし,この関数を必要に応じて引用することによってプログラムを構成します.あるオブジェクトプログラムが引用している関数の本体が別のオブジェクトプログラムに存在する場合,両オブジェクトプログラムを結合する必要が生じます.

関数は次のように表現します.

関数の型 関数名 ( 引数 ) { 処理手順 }

関数の型 とは,関数が出力する値の種類です.例えば,整数値 x を与えれば x + 5 を計算する関数の定義(関数名 plus5)は次のようになります.

int plus5 (int x) { return x + 5; }

(int は整数:integerを表わします.)この関数 plus5 を引用する場合,例えば 6 + 5 を求めたい場合は,次のようにします.

z = plus5 (6);

これにより,関数 plus5 が 6 + 5 = 11 を計算し,得られた値を変数 z に代入します(z はあらかじめ整数型の変数として宣言しておく必要があります).

sample.c の場合,内部に2種類の関数:main(),printf() が現われます.このうち main() は実行ファイルが必ず含んでいる特別な関数です.実行ファイルが起動されると,スタートアップルーチンと呼ばれる特別なプログラムがまず起動し,その内部で関数 main() が引用されます.したがって,実行ファイルを生成するには関数 main() を含むプログラムが必要です.

printf() は,プログラムから出力される値や文字列などを端末上に表示する関数です.sample.c ではこの関数は単に文字列 Hello world! を表示する処理を行なっています(printf() の使用法については,後の回で詳しく説明します).

sample.c にはこの関数 main() の本体が含まれています.一方,printf() については単に引用されているのみで,その本体は sample.c には含まれてません.printf() は標準関数と呼ばれる関数のひとつで,その本体は標準ライブラリlibc.a に含まれています.標準ライブラリはオブジェクトファイルです.リンカ ld は,sample.c から生成されたオブジェクトプログラムとオブジェクトファイル libc.a を結合して実行ファイル a.out を生成します.

Page 1 of 1