目錄
什么是gcc、g++
gcc、g++ 相關操作詳解
預處理、編譯、匯編、鏈接來源
動靜態鏈接是什么
結語
什么是gcc、g++
gcc、g++其實就是編譯器,是幫助我們從.c或者.cc,.cpp文件編譯成可執行程序的
其中,我們如果要編譯c語言文件的話,上面兩個我們都可以使用,雖然g++是用來編譯cpp的,但是cpp本身就包含了c語言
但是我們并不能使用gcc來編譯cpp文件,會報錯的,
接著我們來快速見一下gcc、g++的用法(其實這兩個用法是差不多的,所以接下來主包就只展示gcc的用法):
這上面我們用到了一個 -o 的選項,這其實就是在給生成出來的可執行程序進行一個命名
如果我們不加上 -o 選項的話,那么他會默認將名字改成a.out
gcc、g++ 相關操作詳解
這里要聲明一下,由于gcc、g++底層用的是同樣的東西,只不過默認處理的語言不同,僅此而已,所以我們gcc進行的操作,g++同樣也有,也可以進行
所以,下面主包也同樣是用gcc進行演示
首先,我們的程序要從.c文件變成可執行程序,一共需要經歷四步:
預處理、編譯、匯編、鏈接
對應在gcc中的操作是:
預處理:gcc -E test.c -o test.i
編譯:gcc -S?test.i?-o test.s
匯編:gcc -c?test.s?-o test.o
鏈接:gcc test.o -o test
其實挺好記的,選項就是ESc,其實就看向鍵盤最左上角,有一個Esc退出鍵
而對應后綴就是iso,記著就好了
接著我們來詳細談一談這四個步驟,以及為什么是四個步驟而不是一步到位
預處理
其實這個步驟就干幾件事情:宏替換,去注釋,頭文件展開,條件編譯等等
我們可以簡單來看一看:
我們可以看到,左邊是test.c,右邊是.i,而我們左邊就12行,到了右邊就變成了800多行了,其實在預處理這一步,就是將上面的頭文件展開,注釋去掉等等而已
但還有一個,什么是條件編譯?
其實就和名字一樣,根據不同的條件,編譯不同的代碼:
就是這樣的
編譯
編譯其實就干一件事情,將C語言轉變成匯編代碼
而我們上面預處理那一步,其實還是c語言,只不過變得非常干凈而已
但是這一步,卻是將c變成匯編,如下圖:
我們用vim打開來看看這個.s文件
匯編
這一步傳自上一步編譯,這一步就是將匯編翻譯成二進制
這里就不用vim打開來看了,因為二進制要看的話只會看到亂碼
鏈接
到了最后一步鏈接這里,其實就是將.o文件(在Windows下可能叫做.obj)變成可執行程序
預處理、編譯、匯編、鏈接來源
可能有人會疑惑,你說預處理我能理解,這樣看起來還是比較整潔,替換一下我覺得沒有問題
但是剩下三步是為什么?為什么不能一步到位直接形成可執行程序?
這里我們就需要講一講歷史淵源了
在最開始的時候,電腦剛出來的時候,我們是用二進制進行編程的
就是像這樣的
但是由于這樣子太麻煩了,所以就出現了匯編語言
但是我們匯編的底層還是二進制
接著就是c語言的出現
我們當然可以直接從c變成可執行,但是這樣太麻煩,因為最底層還是二進制,但是如果我們只是將出c變成匯編的話,匯編到二進制那一步我們就不需要做了,因為歷史幫我們完成了,所以效率就很高
所以有四步一方面是歷史原因,另一方面就是效率高了
另外還有一個有意思可以拓展一下的就是:編譯器的自舉
問一個問題,是有匯編語言,還是先有匯編語言的編譯器?
答案當然是現有匯編語言,不然的話匯編對應的編譯器的語法檢查等等東西怎么寫?
但是在最開始的時候,我們只有語言,沒有對應的編譯器,所以我們就會先用二進制寫一個匹配匯編的編譯器,接著就是,我們再用這個二進制寫成的匯編編譯器再寫一個用匯編語言寫出來的匯編編譯器
這時,我們的編譯器就出來了,c語言同樣如此,這就叫做編譯器的自舉
動靜態鏈接是什么
首先是操作,動態鏈接的話是默認的,你用gcc默認就是動態鏈接
如果你要靜態鏈接的話,需要在gcc指令的最后面加上-static
但是可能會遇到如下這種情況:
這代表靜態庫沒有安裝,因為可能有些默認就是沒有靜態庫的,用yum安裝即可
然后要安裝哪一個庫就搜一下對應指令即可,因為一般用不到這個,所以其實不太需要安裝
接著我們需要知道,我們的項目中會包含很多頭文件,但是我們在編譯的時候,會先通過預處理找到庫然后將庫展開代替到項目中的
這就說明,我們的云服務器中,系統中,是一定有對應的庫的,這樣我們才能說去找到他
而在Linux中,我們可以用 ldd 命令來查看
我們可以看到,這里面用到的就是c語言的標準庫
同時我們還可以用file指令看看,具體的鏈接方式:
這里可以看到,就是動態鏈接
但是我們還需要知道,什么是動靜態鏈接?
舉個例子,學校外面有一個網吧,當到了周末的時候,同學們都會去到網吧里面用電腦,因為學校沒有(假設),這時候,我們的網吧就是動態庫,而同學們去網吧的這個過程,就叫做動態鏈接
而靜態鏈接就是,沒有網吧,但是在學生宿舍里面每一個人都有一臺電腦,這時候不管外面有沒有網吧,同學們都不會出去了,因為電腦直接就有了,這就是靜態鏈接
而在我們的Linux中,最主要的就是動態鏈接,因為動態鏈接的優點就是,我們的庫(網吧)只需要有一個就夠了,會省空間,提高效率,但是缺點就是,當我們的這個對應的庫被誤刪的時候,可能會有幾百上千個文件(同學)同時用不了(上不了網)
而靜態庫的優缺點則是相對的,因為這是直接將庫給每個人配一個了
這是動靜態庫大小的對比
我們可以看到的是,這里面都是用到的動態庫,因為本身靜態庫的效率就不高,從這里我們就可以看到Linux對于動靜態庫的態度了
結語
這篇文章到這里就結束啦!!~( ̄▽ ̄)~*
如果覺得對你有幫助的,可以多多關注一下喔