Linux 學習筆記 gcc初體驗

2021-07-11 14:53:19 字數 4387 閱讀 5205

大部分內容**:

用vmware裝了個ubuntu的虛擬機器嗎,前坑未填,又增新坑。

在這裡學了一下,基本的目錄結構:

目錄管理的生存向命令:

vim的基本操作:(。。。)

好了!開始填坑!

ctrl + alt + t 開啟終端

pwd 顯示當前目錄

cd 切換目錄

接下來主要說明gcc的用法:

1. 單個檔案的編譯

首先通過vim建立乙個c文件 口令如下:

vi hello.c

假設程式為:

#include int main()

:wq 儲存並退出

hello.c檔案儲存在當前目錄下

此時輸入口令:

gcc hello.c

執行後,看上去並沒有什麼效果,此時鍵入:ls -al  (顯示當前目錄下所有的檔案及資料夾,包括隱藏檔案,以及它們的詳細資訊)

會發現當前目錄中多出乙個 a.out 的檔案。

試著執行一下 a.out

./a.out

這時終端輸出了「hello world」字樣

如果不想每個生成的可執行檔案都叫乙個名字——a.out

則用如下口令:

gcc hello.c -o run

-o 代表 output

run 輸出的檔案的檔名

這時,輸入:

./run

可以獲得相同的效果

2.多個檔案的編譯

假設我乙個專案裡由多個c檔案組成,main.c , add.c

這時如何編譯

首先:gcc -wall -c main.c 

gcc -wall -c add.c

這時,目錄下會多出main.o , add.o 兩個目標檔案

-c 的作用是只編譯不鏈結 不生成可執行檔案

接下來就要將這些目標檔案進行鏈結,生成可執行檔案。

gcc -wall main.o add.o -o result

此時,當前目錄多處乙個名為result的可執行檔案

./result

執行後即可得到結果。

上述過程看起來十分繁瑣,可以用一句話來概括

gcc -wall main.c add.c -o result

編譯之後產生目標檔案,將目標檔案進行鏈結產生可執行檔案。

3. 靜態鏈結和動態鏈結

此頁說的很詳細,我也就似懂非懂的複製貼上一兩句

「庫說白了其實就是乙個個目標檔案的集合。linux上一共有兩種庫檔案型別,一種是以.a格式的靜態鏈結庫,另一種是以.so格式的動態鏈結庫。下面我們來講講靜態鏈結庫。」

ar的使用格式:

ar cr libname.a file1.o file2.o file3.o …...

注釋:libname.a中字首lib和字尾.a固定,name是靜態鏈結庫的名稱。    

ar cr libtest.a add.o、minus.o、divide.o、multiply.o                        // 將幾個.o的目標檔案整合到乙個庫中

執行命令後,我們檢視當前目錄下的檔案,就多出了乙個libtest.a檔案。接著,我們就直接使用libtest.a來重新編譯源程式:

gcc -wall main.c libtest.a -o result2

程式結果和之前的一樣。我們也可以使用下面這種方法:

gcc -wall main.c -l. -ltest -o result2

// 猜測原文這裡的「.」加的位置可能有問題,經測試發現 -l後面接位址,"."表示當前目錄,因此"."應當夾在-l後面

注意,上面的」-l.」不能缺少,因為,使用」-l「,編譯器查詢的是系統預設的庫檔案位址,而不是當前目錄,故需要使用-l來說明庫檔案位址,由於我們的libtest.a在當前目錄下,故直接使用「.」表示當前目錄。以後,我們向別人提供第三方函式庫時,如果不想讓別人看到源**,那麼就可以只提供.a靜態鏈結庫和包含所有函式宣告的標頭檔案即可。

a.靜態鏈結

在之前所有的教程裡,我們都是把生成的目標檔案、靜態鏈結庫以及標頭檔案放在同乙個資料夾下,這樣不僅顯得很雜亂,也不便管理原始檔,一旦程式的檔案數目龐大後,問題就愈加突出。下面我們就對程式檔案整理一下,一般來說,標頭檔案放在include 資料夾下,靜態鏈結庫lib資料夾下。下面先建立兩個資料夾,並把相應的檔案移動到對應資料夾下。

mkdir include

mkdir lib

mv libtest.a lib

mv math.h include

由於我們已經將四個目標檔案(add.o、minus.o、divide.o、multiply.o)打包成靜態鏈結哭libtest.a,那麼就可以刪除這四個檔案:

rm add.o minus.o divide.o multiply.o

這是當前目錄就只剩下main.c、add.c、minus.c、divide.c、multiply.c這五個原始檔。

首先,我們用比較麻煩的方法一步步地來編譯原始檔,首先是生成目標檔案,由於add.c、minus.c、divide.c、multiply.c這四個源**的目標檔案的已經生成並被打包到靜態鏈結庫中,故我們只需生成main.c的目標檔案即可:

gcc -wall -iinclude -c main.c                              // 我在測試的時候 include 資料夾是放在 programming 資料夾中,因此可寫為 -lprogramming/include ,注意「相對位址」概念

這裡-iinclude中-i後面接的是main.c中所引用標頭檔案(math.h)的位址,這裡使用的是相對位址,其實也可以使用絕對位址,當由於不同的linux系統,他們的檔案位置可能有寫差異,這就造成我們程式的移植性很差,所以還是建議大家使用相對位址。

接下就鏈結目標檔案即可。

gcc -wall main.o -llib -ltest -o result3

可以看到,多個.c檔案編譯後生成的目標檔案,.o檔案,可以集成為乙個庫檔案,即.a檔案,存放到工程檔案目錄中,在鏈結時從目錄中呼叫此庫,即可達到多個.o檔案同時作用的效果。

b.動態鏈結

動態鏈結的乙個好處是,同乙個庫檔案資源,可以供多個程式共享使用,可以省下許多記憶體空間。但是,在移植到另乙個作業系統環境時,如果該系統沒有相應的動態鏈結庫或設定相應的路徑,那麼程式就無法執行,這在移植性方面,相對靜態鏈結方式就差一些。下面開始進入主題:

動態鏈結庫的字尾是.so(在linux上,windows上是.dll)。其命名方式為:lib***.so,

建立方法:

gcc -c -fpic a.c b.c .............

gcc -shared a.o b.o .... -o lib***.so

這裡-fpic:由於共動態鏈結庫不同,他們在執行時載入,因而位址是很隨機的,加上-fpic選項,可以保證編譯生成的東西是位址無關的。

我們這次建立乙個libtest.so動態鏈結庫。

gcc -c -fpic add.c minus.c divide.c multiply.c

gcc -shared add.o minus.o divide.o multiply.o -o libtest.so

現在,我們已經生成了乙個libtest.so動態鏈結庫。

gcc -wall main.c -l. -ltest -o run

-l.表示庫檔案在當前目錄下,-ltest就是libtest.so檔案,注意,這裡不是執行時,而是編譯鏈結過程。。。

現在我們執行run執行檔案,這時,會報錯,說找不到libtest.so檔案。

一、將libtest.so複製到/usr/lib目錄下

二、修改路徑:export ld_library_path=.:$ld_library_path,在路徑下新增當前路徑。

// 缺少許可權未除錯成功,不過概念大概就是這樣

個人臆測動態與靜態的區別:

靜態庫封裝在軟體目錄中,與軟體本體共生,使用靜態庫是為了管理軟體本身。

動態庫則需要隨著軟體的移植,在當前系統中的庫中進行配置。在程式編譯的時候,檢索的是當前系統的庫,是否有對應的動態庫檔案。因此,同乙個庫檔案資源,可以供多個程式共享使用,可以省下許多記憶體空間。

本章內容,操作簡單,偏向基礎原理,主要是為了下一步學習makefile做準備。

django初體驗 學習筆記

django環境搭建 1.安裝python 2.ipython sudo apt get install ipython sudo pip install ipython 3.安裝pip sudo apt get install python pip 4.安裝django pip安裝 sudo pi...

學習筆記 Python Numpy初體驗

numpy numerical python 是 python 語言的乙個擴充套件程式庫,支援大量的維度陣列與矩陣運算,此外也針對陣列運算提供大量的數學函式庫。numpy是用於資料科學計算的基礎模組。建立一維陣列 a np.array 1 2,3 4 print a 建立二維陣列 b np.arra...

jQuery 學習筆記 一 初體驗

hello word 12 345aabb p cc 此示例使用了 1 jquery的id選擇器 btnshow 2 事件繫結函式 bind 3 顯示和隱藏函式.show 和hide 4 修改元素內部html的函式html btnshow bind click function event btmh...