分割コンパイル

C プログラミング
— 分割コンパイル —
早稲田大学
本日の目標
関数のプロトタイプ宣言
分割コンパイルとリンク
ヘッダファイル
関数の使い方
#include <stdio.h>
戻り値の型 関数名(引数の型 引数名){
...
return 戻り値;
/*この関数の戻り値を return 文で指定*/
}
int main(void){
double a;
a = 関数名(引数); /*上の関数を呼び出し,戻り値を a に代入*/
...
}
関数には,引数と戻り値がある
通常,#include 文の後,main 関数の前に書く
(関数が使えるのはソースファイル中のその場所以降)
関数名のルールは変数名と同じ,役割が分かりやすい名前をつけること
return 文で関数を終了する.戻り値はこの時に指定する
関数を使うときは,情報を引数として渡して呼び出し,戻り値を受け取る
関数の使用例
足し算を計算する関数 add を使ったプログラム
#include <stdio.h>
double add(double x,double y){
return x+y;
}
int main(void){
double a,b,c;
printf("Input a:");
scanf("%lf",&a);
printf("Input b:");
scanf("%lf",&b);
c=add(a,b);
printf("a+b=%f\n",c);
return 0;
}
関数の使用例
足し算を計算する関数 add を使ったプログラム(間違い)
#include <stdio.h>
int main(void){
double a,b,c;
printf("Input a:");
scanf("%lf",&a);
printf("Input b:");
scanf("%lf",&b);
c=add(a,b);
printf("a+b=%f\n",c);
return 0;
}
double add(double x,double y){
return x+y;
}
この書き方はエラーになる.
コンパイラが上から下にコンパイルを行なうため,main 関数内での add における引数,戻り
値がわからないので困る.
C 言語ではわからない場合「int 型」として先に進むので注意.
ここでは,int 型として先に進んだが,実際引数も戻り値も double 型だったのでエラーになる.
プロトタイプ宣言
足し算を計算する関数 add を使ったプログラム
#include <stdio.h>
double add(double, double);
int main(void){
double a,b,c;
printf("Input a:");
scanf("%lf",&a);
printf("Input b:");
scanf("%lf",&b);
c=add(a,b);
printf("a+b=%f\n",c);
return 0;
}
double add(double x,double y){
return x+y;
}
これを回避するため,プロトタイプ宣言と呼ばれる宣言がある.
main 関数の前に関数の中身は書かず,関数の名前と引数と戻り値のみ宣言
する.
( ; を忘れずに.
)
分割コンパイルとリンク
分割コンパイルの必要性
実際のプログラムはもう少し長くなる場合がある.
⇒C 言語ではプログラムを複数のファイルに分けて作成できるよう
になっている
分けて作成したファイルは別々にコンパイル(分割コンパイル)し,
最後にリンクすることができる
⇒ コンパイル時間の短縮・同じ関数の使い回し
分割コンパイルとリンクの例
main.c
#include <stdio.h>
double add(double, double);
int main(void){
double a,b,c;
printf("Input a:"); scanf("%lf",&a);
printf("Input b:"); scanf("%lf",&b);
c=add(a,b); printf("a+b=%f\n",c);
return 0;
}
function.c
double add(double x,double y){
return x+y;
}
gcc -c main.c
gcc -c function.c
gcc main.o function.o
./a.out で実行
分割コンパイルとリンク
分割コンパイル
各分割ファイルを「-c」オプションを指定してコンパイルする.
拡張子が「.o」のオブジェクトファイルが生成される.
gcc -c main.c
gcc -c function.c
main.o function.o が作成される
リンク
関連するオブジェクトファイルをリンクし,実行ファイルを作成
gcc main.o function.o
ヘッダファイル
さきほどの例では main 関数のファイルの中にプロトタイプ宣言を
行っていた.
⇒ 関数の定義が別ファイルに入っているため main 関数のファイル
内での宣言が必要.
ヘッダファイルを作成しその中にプロトタイプ宣言を行うことでプ
ロトタイプ宣言も分割する.
ヘッダファイル
プログラムの先頭で「 #include<stdio.h>」と記述してきた
printf 関数や scanf 関数を使用するためにインクルード(読み込み)
していた
C 言語には,関数を集めた標準ヘッダファイルが準備されている
プログラム中で使用する関数に応じて,必要な標準ヘッダファイル
をインクルードする必要がある
例えば,stdio.h:printf, scanf 等のプロトタイプ宣言(入出力関数)
printf.o, scanf.o などのオブジェクトファイルが固められて用意され
ており,コンパイル時にリンクされ実行ファイルに結合される.
数学ライブラリなど意図的にリンクを張らなければいけないものも
ある「-lm」
プロトタイプ宣言を分ける例
main.c
#include <stdio.h>
#include "func.h"
int main(void){
double a,b,c;
printf("Input a:"); scanf("%lf",&a);
printf("Input b:"); scanf("%lf",&b);
c=add(a,b); printf("a+b=%f\n",c);
return 0;
}
function.c
double add(double x,double y){
return x+y;
}
func.h
double add(double, double);
自作のヘッダ(ここでは”func.h”)をインクルードする.
ファイル名を 「<>」 で囲めば設定されたディレクトリのファイルを読み
込む,
「” ”」 で囲めばカレントディレクトリ(今いる)のファイルを読み
込む.
プロトタイプ宣言を分ける例
main.c
#include <stdio.h>
#include "func.h"
int main(void){
double a,b,c;
printf("Input a:"); scanf("%lf",&a);
printf("Input b:"); scanf("%lf",&b);
c=add(a,b); printf("a+b=%f\n",c);
return 0;
}
function.c
double add(double x,double y){
return x+y;
}
func.h
double add(double, double);
gcc -c main.c
gcc -c function.c
gcc main.o function.o
本日のまとめ
関数のプロトタイプ宣言
分割コンパイルとリンク
ヘッダファイル