| 形式 | 搜索順序 | 典型用途 |
#include "file.h" | 1. 當前 .c 文件目錄 2. -I 指定目錄 3. 系統標準目錄 | 項目自有頭文件 |
#include <file.h> | 1. -I 指定目錄 2. 系統標準目錄(如 /usr/include) | 系統/第三方庫頭文件 |
GCC 實例:
# file.h 在 sub/ 目錄下
gcc -c main.c -I sub # 推薦:-I 指定搜索路徑
# 或
#include "sub/file.h" # 源碼中寫相對路徑,無需 -I
二、鏈接階段:從聲明到目標文件
- 編譯期:頭文件提供聲明,生成目標文件
.o,其中函數調用處為「未解析符號」。
- 鏈接期:鏈接器掃描所有
.o 和庫文件,將調用處符號解析為實際地址。
- 關鍵點:聲明(含頭文件)僅告知編譯器「符號存在」,鏈接器負責在目標文件/庫中尋找定義。
三、為什麼需要靜態庫 (.a)?
假設有 judge.o、gen_rnd.o 兩個目標文件:
- 直接鏈接目標文件:
gcc main.c judge.o gen_rnd.o -o main —— 文件多時命令冗長。
- 打包為靜態庫:
ar rs libgame.a judge.o gen_rnd.o # r=替換/添加,s=創建索引
gcc main.c -L. -I. -lgame -o main # -L. 當前目錄找庫,-lgame 鏈接 libgame.a
優勢:
- 命令簡潔:
-lgame 替代多個 .o 文件。
- 按需鏈接:鏈接器只從庫中提取「被引用」的目標文件,未引用的函數(如
judge.c 中新增的無關 add())不會進入可執行文件,減小體積。
四、靜態庫命名與 ar 命令詳解
- 命名規範:
lib.a(lib 前綴 + .a 後綴 = Archive)。
ar rs libfoo.a a.o b.o: