next up previous contents
Next: 2. 分割コンパイル Up: 1. モジュール Previous: 1. モジュール

1. プリプロセッサ

これまで我々は一つのファイルに全ての関数を記述する事でプログラミング を行って来た。C言語では一つのファイルにまとめられたプログラムの単位 をモジュールと呼ぶ。すなわち、我々はこれまで一つのモジュールのみで プログラムを行って来たのであるが、C言語ではモジュールは複数存在して いても問題ない。そこでの問題は前述したように情報の共有方法のみである が、関数の宣言などの情報の共有は実は簡単で、関数の宣言はモジュール毎 に同じ宣言を行えば良いようになっているのである。 つまり、 多くの関数を含むC言語のソースにおいて、 関数宣言はファイルの先頭に次のように まとめられているだろう。


     int   test1(void);
     char  test2(int, int);
     char *test3(char *);

そこで、このプログラムのソースを二つに分けて開発するとすると、 両方のプログラムソースの先頭にこの宣言があれば良い。つまり、 関数宣言的には、この同じ行を2つのモジュールの先頭にコピー すれば良いのであるが、当然この場合書き換えや訂正をしたら、 同じ事を両方のモジュールの先頭のこの宣言に対して行わなければ ならず、常に双方を同じに保つのは意外と面倒であろう。

こうしたことを簡単化するために、この記述自体を一つのファイルにしてしまい それらを利用したいモジュールに自動的に取り込んでくれるような仕組みがあれ ば便利であろう。このために、C言語にはコンパイル以前に一連の仕事を行う 仕組みが用意されており、それはプリプロセッサと呼ばれている。 プリプロセッサは指示に従い、コンパイル以前に(プリ)、処理(プロセス)を 行うためのもので、別に用意されたファイルをプログラムソース中に取り込む こともその役割の一つになっている。

このようにしてプリプロセッサを利用した例が以下のものである。


/* file: head.h */
     int   test1(void);
     char  test2(int, int);
     char *test3(char *);

このファイルが head.h と言う名前になっている場合、このファイルの中身を ソースファイルに取り込むには以下のようにする。


/* program souce */
#include "head.h"
...
main(){
    ...

ちなみに、c のソースファイルの拡張子に .c を付けるように、上記の ような宣言などをまとめたファイル(ヘッダーファイルと言う)は .h を拡張子に用いる。

既に気が付いたように、今まで呪文としてプログラムソースの最初に記述して来た

#include <stdio.h>
#include <stdlib.h>
とほとんど同じである事が分かるであろう。つまり、この #include <stdio.h> などは、ライブラリに含まれる関数の宣言など を記述したファイルを取り込んでいた訳である。しかし、少し違いもある。 この違い(<>"" で括った違い)は、このヘッダーファイルが どこにあるかという違いに起因した違いで、<> で括った場合には デフォルトの場所(例えば、/usr/include/ など)のみを探すが、 "" で括った場合にはカレントディレクトリ をまず探し、なければデフォルトの場所も探すようになっている(デフォルトの 場所以外の場所を探すような事も出来るが、ここでは説明を省略する)。通常、 標準ライブラリの場合には <> で括り、自分で作成したモジュール に関連するヘッダーの場合には "" で括るようにすれば良いであろう。

また、記述の順序は標準ライブラリから記述するのが通常であり、そうでないと 問題が生じる場合がある(これについては機会があれば別の箇所で触れよう)。 従って、結局以下のようにプログラム先頭に記述することになる。


#include <stdio.h>
#include <stdlib.h>

#include "head.h"
...
main(){
   ...

勿論、モジュールファイルの先頭にも同じように書くのを 忘れてはならない。

プリプロセッサのコマンドには他にも多くの重要なものがあるが、それに ついては別の章で触れることにする。



Noriyo Kanayama