一、gcc\g++編譯器
什么是gcc和g++,它們的區別又是什么?
gcc編譯器是專門用來編譯C語言的,而g++編譯器既可以編譯C語言又可以用來編譯C++,但是主要還是用來編譯C++。
我們都知道代碼形成可執行程序都是需要經過預處理、編譯、匯編和鏈接這四個過程的,既然如此上述我們看到的兩個編譯器也必然是要圍繞著這四個過程來進行說明。
1、預處理
預處理是做是什么工作的?
頭文件展開、宏替換、去掉注釋和條件編譯
我們在linux中輸入什么指令可以看見預處理這個階段呢?
filename.c為要編輯的文件名
gcc -E filename.c 將預處理后的內容打印到顯示屏上
gcc -E filename.c -o test.c 將預處理后的內容寫到test.c文件里
什么是頭文件展開呢?
頭文件展開其實就是把頭文件中相關的內容拷貝到源文件中,也就是說當預處理完成后我們其實就可以不用頭文件了
什么是裁剪?我們又怎么理解裁剪呢?
裁剪其實就是對代碼進行增、刪和改操作。在預處理階段,我們會發現代碼從原來的幾行一下子變成了幾百行,這其實就是將頭文件里面的內容拷貝到了源文件中了這里就是增,之后去掉注釋這里就是刪,最后根據條件可以修改代碼這就是改。
2、編譯
實現編譯的操作
gcc -S filename.c -o test.c 對預處理階段的文件進行編譯
我們可以看到當我們輸入上述指令后,會形成一堆我們看不懂的東西,而這個東西是什么呢?其實就是匯編語言。
3、匯編
實現匯編操作
gcc -c filename.c -o test.c 對test.c進行匯編
經過上面的編譯生成的匯編,而這里的匯編是生成可執行程序當中的一個階段。它其實就是將匯編語言翻譯成可重定位目標二進制文件。這里我們就有疑問了,既然它是翻譯成二進制文件,是不是到這里我們計算機就可以識別了呢?并不是我們可以嘗試使用./test.c來運行這個程序
我們發現直接就是報錯了,這是為什么呢?我們接著往下看。
4、鏈接
實現鏈接的操作
gcc filename.c -o test.c
上面的匯編形成的可重定位二進制文件并不是一個可執行程序,它必須要經過鏈接才能生成可執行程序。這又是為什么呢?
比如在編程時,我們經常使用現成的庫函數,而不必每次都重新編寫所有功能代碼,只需聲明即可調用。同樣,匯編生成的可重定位二進制文件也需要與庫函數鏈接,才能最終生成可執行程序文件。
那么什么是鏈接呢?
在代碼編譯階段,庫函數的實際地址尚未確定,因為這些函數的具體實現位于庫文件中。當進行鏈接時,鏈接器會將目標文件(.o)與庫文件合并,在此過程中會解析并填充庫函數在目標文件中的調用地址,最終生成完整的可執行文件。
為什么要有庫?
使用庫的主要目的是提升開發效率。在日常開發中,我們經常需要重復使用某些功能函數。如果每個開發者都自行編寫這些基礎功能,會造成大量重復勞動和時間浪費。
如何理解庫呢?
庫的常見分類有兩種:靜態庫和動態庫
在windows中后綴分別是:.lib 和 .dll
在linux中后綴分別是:.a 和 .so
動態鏈接:與動態庫鏈接
靜態鏈接:與靜態庫鏈接
注意:
靜態鏈接有可能會失敗,原因是因為系統中可能沒有默認安裝C\C++的靜態庫。編譯器默認采用動態鏈接的方式,形成可執行程序。
什么是動態鏈接?
動態鏈接就是程序還未加載到內存的時候,就已經和動態庫建立了信息上的鏈接,執行到庫函數的時候,跳轉到動態庫執行,然后繼續執行自己的代碼
優點:節省資源
缺點:一旦丟失所有的程序都將無法運行
什么是靜態庫?
一組編譯好的代碼和數據的集合,它們在編譯期間被鏈接到應用程序中
優點:不依賴任何庫,自己獨立就能運行
缺點:體積大,占據資源多,加載速度受影響
二、自動化構建make\Makedife
1、基本概念
make是一個linux系統內置的命令
Makefile是一個需要自己創建的文件
make命令會在當前目錄下尋找makefile文件,解析里面的內容
2、操作步驟
(1)創建makefile文件
(2)編寫makefile文件
(3)make指令運行代碼
3、makefile
這里我們會有很多的疑問。
為什么make的時候只執行了第一個目標呢?
這是因為make,makefile默認只形成一個目標,就是從上往下遇到的第一個目標
什么是偽目標?
.PHONY:表示被修飾的目標是一個偽目標
特點:偽目標總是被執行的。