法大奥山研究室

 previous  contents

16.5. ソースファイルの分割と外部参照の解消


 以上で,プログラムを分割し,関数やオブジェクトをリンクさせるためのプログラミング技術の知識は終わりです。ここでは簡単なプログラム分割を行い,各ソースファイルで個別に定義された関数やオブジェクトをリンクさせてみます。

 分割前のプログラムは最初に見た例 Example 16.0 にオブジェクトを加えた単純なものです。

/* Example 16.6 */

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

void myPrint(char *);
char head[] = "Welcome!";

int main (void)
{
       char str[8] = "test";
       myPrint(str);
       exit(0);
}

void myPrint(char *x)
{
       printf("%s\n", head);
       printf("This is a %s.\n", x);
}

プログラムの分割は,以前同様,メインの処理部分(main.c というファイル)とプリント関連部分(myPrint.c というファイル)への二分割です。

/* main.c */

#include <stdlib.h>

void myPrint(char *);
char head[] = "Welcome!";

int main (void)
{
       char str[8] = "test";
       myPrint(str);
       exit(0);
}
/* myPrint.c */

#include <stdio.h>

void myPrint(char *x)
{
       printf("%s\n", head);
       printf("This is a %s.\n", x);
}

しかしながら,myPrint関数は,main.c で宣言されている文字列 head を必要とします。実際,myPrint.c のみコンパイルしてみると,

cc -c myPrint.c
myPrint.c: In function `myPrint':
myPrint.c:7: `head' undeclared (first use in this function)
myPrint.c:7: (Each undeclared identifier is reported only once
myPrint.c:7: for each function it appears in.)

という具合に head が宣言されていないというエラーが出ます。そこで利用するのが「リンケージ」です。この場合,myPrint.c が外部参照するオブジェクトなので,extern を使います。myPrint.c のプリプロセッサ(#include <stdio.h>)の次に,次を書き加えてみます。

extern char head[];

これで上のエラーメッセージが出なくなるだけなく,main.cheadmain.c に残しておくことが可能となります。

 myPrint.c に書き加える方法は,確かに有効です。しかしながら,今後作成しうるモジュールでも変数 head を利用するかもしれません。そこで,main.c 固有の変数や関数をまとめたヘッダファイルを用意するのが良いかもしれません。

/* main.h */

extern char head[];

このようにしたら,myPrint.c は次のようにすれば良いこととなります。

/* myPrint.c */

#include <stdio.h>
#include "main.h"

void myPrint(char *x)
{
       printf("%s\n", head);
       printf("This is a %s.\n", x);
}

myPrint.c 内独自の関数やオブジェクトが書かれているヘッダファイルも同様に作成しておくと便利かもしれません。

/* myPrint.h */

extern void myPrint(char *);

このようにしたら,main.c は次のようにすれば良いこととなります。

/* main.c */

#include <stdlib.h>
#include "myPrint.h"

char head[] = "Welcome!";

int main (void)
{
       char str[8] = "test";
       myPrint(str);
       exit(0);
}

これでソースの分割は完了です。プログラムは,main.cmain.hmyPrint.c,そして myPrint.h の4つのファイルから構成されることとなった訳です。各ソースファイルの依存性も明確になったと思います。

■コンパイル

各ソースをコンパイルしてみましょう。

cc -c main.c
cc -c myPrint.c

成功すればオブジェクトファイル main.omyPrint.o が出来上がります。成功したらそれらをリンクさせます。

cc main.o myPrint.o

これで実行ファイルが出来上がります。

 main.c あるいは myPrint.c を書き換えた場合には,書き換えたソースのみを再コンパイルします。というのは,一度生成したオブジェクトファイルは,常時,利用可能だからです。(Makefile を利用すると,書き換えを自動検知してくれます。次の「付録 Makefile」を。)


 previous  contents