参考書を読んで分割コンパイルという技術を知ったので、
今回はアウトプットかつ知識の整理ということで、
初めてソースファイルを分けてプログラムを実行する分割コンパイルを行ってみました。
まあ日記のような感じです。
分割コンパイルとは?
今まで僕の記事ではいつも、「全体のコード」として作った関数などをすべて一つのソースファイルの中に書き込んでいました。
今回はいくつかの関数だけ違うファイルにして、違うファイルからそれを呼び出してプログラムを実現してみます。
いわゆる分割コンパイルです。
普段僕たちはprintf関数を使っていますがあれは自分で書いたコードでは定義してないですよね?
最初に<stdio.h>というライブラリをインクルードすることで使用が可能になります。
つまり、<stdio.h>というライブラリの中で既にprintf関数を作ってもらってて、僕たちはその内容は知らないけどprintf関数は取りあえず使える状態ですって感じです。

分割コンパイルで別のファイルを作って利用するのも同じイメージです。
今回はそんなライブラリみたいなものを作ってみます。
ソースファイルとヘッダファイル
早速新しいファイルを作ろうと思って
Xcodeで新しいプログラムを開いてメニューバーから新しいファイルを追加したのですが、


あれ?同じ名前のファイルが2つある?

はい。分割コンパイルの際の別のファイルには
ヘッダファイル(.hで終わるやつ)
ソースファイル(.cで終わるやつ)
の二つのファイルがあります。
簡単に解説すると
ヘッダファイルは構造体やマクロの定義、そして関数原型宣言などのみを行うファイルです。
ソースファイルは宣言した関数の中身を記述するファイルです。中身を記述する前に、ヘッダファイルをインクルードします。
僕の頭の中のイメージ図です↓

この二つを揃えることが必須です。
ヘッダファイルを作っておくことで、このソースファイルではこんな感じのやつを定義するから準備しとけよっ!!って感じですかね。
そしてメインとなるソースファイルで
ヘッダファイルをインクルードすればおkです
ちなみに全体としては

こんな感じ。
つまり、実行する方のソースファイル(上の画像ならprogram.c)と、
分割された関数の中身が記述されているソースファイル(上の画像ならfile.c)
は直接つながってないんですね。

ヘッダファイルのみを介して繋がってる感じですね。
簡単なコード
ファイル操作関数を実際に分割コンパイルしてみました。
まずヘッダファイル
#ifndef file_h
#define file_h
void SCAN(int N, double x[N], char *name);
void WRITE(int N, double x[N], char *name);
#endif /* file_h */
そしてそのソースファイル
#include <stdio.h>
#include "file.h"
void SCAN(int N, double x[N],char *name){ //読み込み用関数
FILE *fp;
int i;
if((fp=fopen(name,"r"))==NULL){
printf("ファイルを読み込めません\n");
}else{
for(i=0; i<N; i++){
fscanf(fp,"%lf",&x[i]);
}
}
fclose(fp);
}
void WRITE(int N, double x[N], char *name){ //書き込み用関数
FILE *fp;
int i;
if((fp=fopen(name,"w"))==NULL)
printf("ファイルに書き込めません\n");
else{
for(i=0; i<N; i++){
fprintf(fp,"%lf\n",x[i]);
}
}
fclose(fp);
}
最後に実行するファイル
#include <stdio.h>
#include "file.h"
#define NAME 64
int main(int argc, const char * argv[]) {
char name[NAME];
int i;
printf(":");
scanf("%s",name);
int N=3;
double x[N];
for(i=0; i<N; i++){
x[i] = 0;
}
WRITE(N, x, name);
double y[]={1,1,1};
SCAN(N, y, name);
for(i=0; i<N; i++){
printf("%f\n",y[i]);
}
return 0;
}
こんな感じですね。
ヘッダの、
#ifndef file_h
#define file_h
#endif /* file_h */
この条件コンパイルの部分はインクルードガードです。
後に紹介しようと思うのでとりあえず今回はおまじない的な感じで。
分割コンパイルは大規模なコードを書くときに必要らしいのでマスターしたいですね。
ではまた〜
コメント