make (makefile) と分割コンパイルの話 今までのプログラム 一つファイルの中に、 main 関数と main 関数から呼び出される、関数を、 一つのファイルに保存した 従来の手順 cc -c p-003.c -- コンパイル cc -o p-003.exe p-003.o -- リンク ./p-003.exe -- 実行 実は、分ける事もできる !! これまでも、printf は、他の場所にあった !! s_xxx.h も、関数の定義は、main 関数とは別 !! ライブラリは、基本、別ファイルに関数が定義されている 分けてみる main -> p-004.c func -> p-004-01.c 実行手順 cc -c p-004.c -- コンパイル cc -c p-004-01.c -- コンパイル すべての .c ファイルをコンパイルし、それぞれ .o を作る cc -o p-004.exe p-004.o p-004-01.o -- リンク リンクする時には、すべての .o を指定する必要がある ./p-004.exe -- 実行 分割コンパイル p-003.c -> p-004.c -> p-004.o ---> p-004.exe p-004-01.c -> p-004-01.o -+ 手間と安全性(バグがあったときに対応可能)がトレード この手間も減らしたい makefile で対応する 手間が増える !! (そんな損をして)何がうれしいか ? 分離した関数が再利用できる p-004.c をコピーして p-005.c (p-004.c 同じく、func 呼び出す が、呼び出し方が異なる ) を作る 実行手順 cc -c p-005.c -- コンパイル cc -o p-005.exe p-005.o p-004-01.o -- リンク リンクする時には、p-004-01.o には、関数 func の定義がコンパイル済 再利用できる ./p-005.exe -- 実行 p-006.c は、p-003.c (関数 func が同居)をコピーして、 main だけ変更する。 これでも、p-003.c の func が、 p-006.c で「再利用」されている と考えててもよさそう... もし、func を変更したくなったら.. ?? 特に、func に問題があって、すべての func を変更したい func : p-003.c, p-004-01.c p-006.c の三か所にある p-003.c ------------> p-003.o -> p-003.exe +-> p-004-01.c -> p-004-01.o -> p-004.exe | -> p-005.exe +-> p-006.c ----> p-006.o ----> p-006.exe p-003.c p-006.c : func の内容をコピーした -> 変更は、両方に行う必要がある p-004.c p-005.c : func の内容を共有した -> 変更は、一か所で済む 手間をかける、結果的的にあとの手間を減らす 技術屋は、その手間をさらに、減らす事を考える make を使えば、手間が減らせる事が解っている == 先週の課題 20160602-01 高さ 3 のハノイの塔の問題を解く 1 2 3 --------- A B C | v 1 2 3 --------- A B C 動かせるのは、一度に一つ 一番上のものだけ 小さい円盤上には、大きな円盤はのせされない 1,2,3 の三つ円盤を A から B に移すという課題なので、 どこかで、A から B に 3 の円盤を動かす必要がある その時には A に 3 があり 3 の上には、何ない B にも何もない -> 1, 2 の円盤は C にある 3 を動かす前に、1,2 を A から C に動かす必要がある 同様に考えると、 2 を A から C に動かすときには、 1 は、B にある必要がある a) 1 を A から B 1 1 2 2 3 3 --------- --------- A B C A B C b) 2 を A から C 1 1 2 2 3 3 --------- --------- A B C A B C c) 1 を B から C 1 1 2 2 3 3 --------- --------- A B C A B C d) 3 を A から B 1 1 2 2 3 3 --------- --------- A B C A B C 後は、C にある 1, 2 を B に持ってくる これは、すでに、A にある 1, 2 を C に持っていった 経験があるので、それを生かせばよい a) 1 を A から B b) 2 を A から C c) 1 を B から C d) 3 を A から B 残りは、a,b,c を参照 先週の課題 20160602-02 高さ n のハノイの塔の問題を解く 手順を人間がやるのは大変なので、やってられない コンピュータに解かせよう [考え方] n=3 の時、 3 の円盤を動かすには、 まず、1,2 の円盤を、まずどかして 3 を動かしたから、 再び、1,2 の円盤を、 3 の上に乗せる -> 一般化 [1 - n-1] [1 - n-1] [ n ] [ n ] A B C x) [1 - n ] を A から B に移動 => a) [1 - n-1] を A から C に移動 b) [ n ] を A から B に移動 c) [1 - n-1] を C B に移動 x) のためには、a), b) の処で再帰呼び出しをすればよい == 問題を解くのに、数学的帰納法の考え方が利用されている 「hanoi(n) を解くために、hanoi(n-1) が利用されている」 この考えを直接、人間が考えて(計算して)手順を作る -> 課題 1 手順(計算結果)が分かったので、それをそのまま記述 考え方がわかれば、後は、計算機に考えて(計算して)手順も、計算機に屋良らセル -> 課題 2 考え方が分かった、考え方を記述した 再帰の「記述=帰納法の考え方を表現したもの」によって、手順が計算される