Skip to content

多檔案專案:從程式碼到軟體

當專案變大時,把萬行程式碼塞在一個檔案裡會變成災難。我們需要將功能拆分,並透過「標頭檔」與「編譯器」將它們重新連結。

檔案的拆分:Header 與 Source

  • .h (Header File):只寫函數宣告和變數宣告,告訴別人「我有這些功能」。

  • .c (Source File):負責寫出函數具體的實作內容。

#include "" vs <>

  • <stdio.h>:去系統標準庫找(通常是 C 語言內建的)。

  • "my_tool.h":去當前資料夾找(自己寫的)。

跨檔案的變數控制

當檔案變多,變數的「可見度」就變得非常重要,這就是 Linkage (連結性) 的概念。

  • extern (對外廣播): 告訴編譯器:「這個變數在別的檔案已經定義過了,請讓我這裡也能用它。」

  • static (內部隱身): 當 static 放在全域變數前,它會把該變數鎖在檔案內。即便別人在其他檔案寫 extern 也抓不到它。這能有效防止「命名衝突」。

編譯工具

傳統手工: GCC

最一開始的時候有介紹過 gcc 編譯,但如果專案有 100 個檔案,每次改一行都要全部重編,會非常浪費時間。

bash
gcc main.c tool.c -o my_app

簡單好用: Makefile

make 是一個聰明的工具 (linux only),它會檢查「檔案最後修改時間」。如果 tool.c 沒動過,它就跳過不編,只編你改過的部分。

Makefile 範例:

makefile
# 定義目標 (target): 依賴項 (dependencies)
all: main.o tool.o
	gcc main.o tool.o -o my_app

main.o: main.c
	gcc -c main.c

tool.o: tool.c
	gcc -c tool.c

跨平台的現代標準: CMake

Makefile 雖然強大,但在 Windows (Visual Studio) 和 Linux 之間的語法不互通。CMake 則是「產生編譯指令的工具」。它不直接編譯程式,而是產生適合該環境的 Makefile 或專案檔。

CMakeLists.txt 範例:

CMake
cmake_minimum_required(VERSION 3.10)
project(MyProject)

# 只要這一行,它會自動處理相依性
add_executable(my_app main.c tool.c)

編譯流程:

  1. cmake . (產生編譯設定檔)
  2. make (開始編譯)
進階:編譯的四個階段

初學者常以為按下 Run 就結束了,但底層經歷了:

  • 預處理 (Preprocess):處理 #include 和 #define。

  • 編譯 (Compile):把 C 變成組合語言。

  • 組譯 (Assemble):把組合語言變成 0101 的目的檔 (.o)。

  • 連結 (Link):把所有 .o 檔拼成最終的執行檔。這是 extern 找不到變數時會噴 Linker Error 的地方。