編輯器 Vim
前導知識
在Linux系統中,開發工具都是獨立的
- 寫代碼 : 編輯器 vim
- 編譯 : gcc / g++
- 調試 : gdb / cdgb
- 構建工具 : makefile / make / cmake
- git
Vim的模式 ( 3 + 2 )

命令模式
vim的默認模式
- 跳到文本末 :
shift + g; 跳到第n行:n + shift + g - 到文本開始 :
gg - 跳到當前行末:
shift + 4 --- $ - 跳到當前行始:
shift + 6 --- ^ - 按照單詞為單位向右移動:
w; 按照單詞為單位向左移動:b - 複製:
yy || n + yy - 貼上:
p || n + p - 刪除:
dd || n + dd - 快切大小寫:
shift + ~ - 替換當前光標位置所在的一個字符:
r || n + r--- 替換模式可以批量化替換 - 刪除光標位置右的n個字符:
n + x; 如果要刪除左的話則是n + shift + x - 撤銷:
u; 對 u 的撤銷進行撤銷:ctrl + r--- 一旦退出了 vim 就無法再做撤銷動作
底行模式
- 強制保存退出:
wq!--- 涉及權限問題 ; 退出也可以用shift + zz相當於wq - 匹配搜索:
/key + n - 不退出vim,直接對代碼編譯執行:
!cmd - 將 a 字符全部替換成 b:
%s/src/dst/g - 分屏操作:
vs; 切換分屏:ctrl + w--- 是用多文件代碼 .h .c 之類的
如果vim打開,突然終端退出 ( 未對目標文件進行儲存 ) 那麼vim會形成一個臨時文件,默認在當前路徑下的一個.swp。
此外,vim退出在光標若在第n行,則重新開啟時依然在第n行。
編譯器 gcc / g++
- gcc : 只能用來編譯C語言
- g++ :可用來編譯C/C++
兩個其實是一樣的,在Linux中,對於程序編譯的過程是一步到位的
一個程序是如何產生的?
預處理(.i)
- 展開標頭檔
- 進行micro替換
- 去注釋
條件編譯 (為什麼要有條件編譯?-> 討論免費與收費功能)。
- 條件編譯本質是對代碼進行裁減!
如何證明預處理做的事情?
gcc -E src -o dst


編譯
- 產生匯編代碼(.s)。
gcc -S src -o dst


- 產生匯編代碼(.s)。
匯編(.o)
- 生成機器可識別代碼 => 把匯編轉成二進制文件(可重定位目標二進制文件)。
gcc -c code.s -o code.o


- 生成機器可識別代碼 => 把匯編轉成二進制文件(可重定位目標二進制文件)。
鏈接
- 生成.exe或庫文件
gcc code.o -o code

- 生成.exe或庫文件
幾個小問題
- 二進制文件可否直接執行?

二進制文件無法直接執行 => 因爲這個二進制文件是可重定位目標二進制文件 => 在我們展開的標頭檔中用到的庫方法都只是聲明! 動態庫與靜態庫
Linux中,動態庫是.so檔,而靜態庫是.a檔- 動態庫
在動態鏈接中,程式並不會把庫函數的實現直接拷貝到可執行檔,而是保留「引用關係」。
標頭檔(.h)只提供函數宣告,真正的實現則存放在動態庫(.so / .dll )中。
當程式啟動時,作業系統會把所需的動態庫載入記憶體,並建立函數的地址表。當執行到某個函數時,程式就透過這張表 跳轉到動態庫中的對應函數,然後再返回程式繼續執行。這也意味著,如果動態庫缺少目標函數,程式將無法正常運行。這種方式稱為動態鏈接 - 靜態庫
在靜態鏈接中,編譯器會在鏈接階段,將所需的庫函數實現直接拷貝到可執行檔中(.a / .lib)。一旦可執行檔生成並成功鏈接,程式執行時就不再依賴靜態庫的存在。這種方式稱為靜態鏈接。

- 動態庫
make / makefile
前導知識:make 是一條指令 makefile 是一個文件
直接先來瞧一瞧make 與makefile

- 目標文件:藉由make後生成的文件名稱
- 依賴文件列表:要生成目標文件,依賴於哪些文件?
- 依賴方法:構建可執行文件的方法
細節部分
(1) 依賴關係必須存在,但是依賴文件列表可以為空
(2) 依賴方法可以是任何shell指令
(3) clean 目標,只是利用make的自動推導能力,使其執行rm指令,在構建工程的視角下,看起來就是清理項目,本質就是刪除不需要的臨時文件!
(4) 當 make 後面跟上某個目標(文件名)時,它只會解析該目標所對應的依賴關係和方法
如果不指定目標,make 預設會從 Makefile 中的第一個目標開始,並且只會沿著這個目標的依賴關係推導出一條完整的構建鏈
make指令其實就是去解析makefile中的內容
如何清理?


- .PHONY:????? --- 用來修飾的文件是一個偽目標,這個文件的本質是
總是被執行的 為什麼.exe不使用.PHONY???? --- 為了提高編譯效率 ( 源文件有被修改時才需要再次編譯 )
如何判斷源文件是否被修改?為什麼未修改的文件不會再次編譯?
- 判斷源文件是否被修改,通常是通過檢查文件的修改時間(Modify time)。如果源文件的修改時間晚於生成的 .exe 檔案,表示源文件已被更新,make 就會重新編譯。
- 如果對目標使用 .PHONY,make 每次執行時都會認為目標需要執行,導致每次都重新編譯,這會增加不必要的編譯開銷
為什麼Modify時間會影響Change時間?
- 當我們修改文件內容時,文件的 Modify 時間會更新。而內容的變動通常會影響文件大小,因此也會連帶改變 Change 時間。此外,Modify 時間本身也是文件的一個屬性
不斷訪問同一份文件,access時間竟然不會一直變?
- 由於修改文件屬性時需要將變更刷新到硬碟上,如果每次訪問都立即更新,將大幅增加對硬碟的訪問次數。而硬碟屬於外部設備,訪問速度相對較慢,這樣會導致整體效率下降,甚至影響整個作業系統的性能。因此access的時間通常是在訪問特定次數後才會更新一次
多個源文件怎麼辦?
多個源文件難道需要一個一個寫入嗎?
構建通用Makefie!
BIN=code.exe
#SRC=${shell ls *.c}
SRC=$(wildcard *.c)
OBJ=$(SRC:.c=.o)
CC=gcc
Rm=rm -rf
$(BIN):$(OBJ)
@$(CC) -o $@ $^
%(.o):%(.c)
@${CC} -c $<
.PHONY:clean
clean:
@$(Rm) $(OBJ) $(BIN)