hw0304 makefile

在這一題makefile可以看看助教給的關係圖,接著看看助教在作業給的最後一句,You need to implement two different functions in another C code and prepare a header file.,根據助教給的資料,以及TA hour助教說的東西,我自己的理解是這樣的,助教要我們提供三個.c檔,一個是主程式,也就是我們要call function的hw0304.c檔,一個是用迴圈實現的函式,一個是遞迴實現的函式,此外要我們寫一個header file,且該header file裡面會僅放一個函式的宣告,藉由將不同的程式揉在一起,來實踐不同的方式,我想這樣講可能有聽沒有懂,我來用我的資料實際示範一次。
首先我們會有三個檔案,分別是hw0304.c, hw0304-1.c, hw0304-2.c, hw0304.h,各個檔案的內容大概會長的像這樣(以下只是範例,但基本上大同小異)。
hw0304.c

#include <stdio.h> #include <stdint.h> #include "hw0304.h" int main(){ printf("Please enter the disk number (2-20): "); int32_t n; scanf("%d", &n); hanoi(n, 1, 2, 3, 1); return 0; }

hw0304-1.c

#include "hw0304.h" void hanoi(int32_t n, int32_t a, int32_t b, int32_t c, int32_t disk){ // loop method }

hw0304-2.c

#include "hw0304.h" void hanoi(int32_t n, int32_t a, int32_t b, int32_t c, int32_t disk){ // recursion method }

hw0304.h

#ifndef _HW0304_H_ #define _HW0304_H_ void hanoi(int32_t n, int32_t a, int32_t b, int32_t c, int32_t disk); #endif

首先請看一下助教給的關係圖,可以看到說助教把hw0304.h的箭頭同時指向hw0304-1.c, hw0304-2.c, hw0304.c,這三個檔案,同時這三個檔案都會include hw0304.h,這是因為我們已經在hw0304.h裡面include一些常用函式,或是定義好的macro,因此我直接在hw0304-1.c, hw0304-2.c, hw0304.c這三個檔案中include hw0304.h就可以直接使用已經被定義好的macro了,而這就是為何助教在關係圖中要我們include hw0304.h的原因。

好如果上述的東西懂了我們接下來請將注意力放在我們宣告函式的地方,可以發現hw0304.h裡面只有宣告一個函示叫做hanoi(int32_t n, int32_t a, int32_t b, int32_t c, int32_t disk),我一開始會納悶,為什麼只需要宣告一種函示,不是應該宣告兩種函示嗎?

void hanoi_recursion(int32_t n, int32_t a, int32_t b, int32_t c, int32_t disk); void hanoi_loop(int32_t n);

一種是迴圈版本一種是遞迴版本,而後來我才理解助教給的關係圖中巧妙的地方。我們之所以只需要一種hanoi()函示是因為我們將不同的.c檔揉在一起,其實作的內容就會依照我們給的.c檔去執行,不太懂嗎?看看這個:

gcc -c hw0304.c hw0304-1.c
gcc hw0304.o hw0304-1.o -o hw0304-1

hw0304-1.c是我們的遞迴版本,這兩道指令的意思是先把hw0304.c和hw0304-1.c編譯成object file,接著再將hw0304.o和hw0304-1.o揉成hw0304-1,就是因為這樣我們可以得到一個執行檔,是由遞迴實作的,因為很清楚的告訴他說我們要使用hw0304-1.c中實作的內容。也就是說我們在hw0304.h中定義了prototype之後,我們再各自去實作他的內容,這樣我們不用定義一堆函數,我們可以藉由這樣的方式寫出一個很漂亮的code。

那我一開始想說這個方法很漂亮,但是在迴圈版本我會傳入一堆沒有用的變數呀,因為迴圈版本只需要傳入

n而已,而hubert和廖俊翔就跟我說沒關係,反正我們就傳入,有沒有用到也沒差,聽完覺得的確是如此。

總結一下這篇筆記在說的事情,首先我們的目的是編譯出一個由遞迴實作的hw0304-1這個執行檔,以及由迴圈實作的hw0304-2這個執行檔,所以我們寫一個hw0304.h定義hanoi(int32_t n, int32_t a, int32_t b, int32_t c, int32_t disk);,定義出他的prototype,接著我們各自寫hw0304-1.c和hw0304-2.c,裡面會有hanoi(int32_t n, int32_t a, int32_t b, int32_t c, int32_t disk)函式分別使用遞迴和迴圈方式實作的內容,最後我們寫一個hw0304.c來include hw0304.h,由於只有include hw0304.h,我們還要另外將hw0304-1.o和hw0304-2.o分別與hw0304.o柔在一起,這樣我們的hw0304.o才會知道hw0304.h裡面宣告的hanoi(int32_t n, int32_t a, int32_t b, int32_t c, int32_t disk)實作的方式是什麼。

我想這個地方有點繞口,畢竟有非常多的檔案,這也是他會稍微複雜的地方,那如果連編譯那邊都看不懂,我想你該去二刷、三刷一下L紀的影片了,影片連結我放在Reference裡面,可以自己去看,我自己也看了不少次,以上是我對hw0304中makefile的理解以及想法,若有問題歡迎一起討論!

最後最後我附上我這題的makefile,請自己斟酌參考一下。
makefile

all: 
    gcc -c hw0304-1.c hw0304-2.c hw0304.c
    gcc hw0304-1.o hw0304.o -o hw0304-1
    gcc hw0304-2.o hw0304.o -o hw0304-2

Reference

https://www.youtube.com/watch?v=7nyTntpXVFk&t=3161s