欧美vvv,亚洲第一成人在线,亚洲成人欧美日韩在线观看,日本猛少妇猛色XXXXX猛叫

新聞資訊

    文章目錄

    一、gcc 演示翻譯環(huán)境

    二、動靜態(tài)鏈接庫

    三、gcc 選項匯總

    一、gcc 演示翻譯環(huán)境

    我們寫的代碼如何編譯?這就要用到我們今天講的內(nèi)容 —— gcc 編譯器。

    在 Linux 中,C 語言用 gcc 編譯;C++ 用 g++ 編譯。

    對于一個 C 程序,從源文件到形成可執(zhí)行程序一共要進行四步:預(yù)處理、編譯、匯編、鏈接 。這四步過程被稱為 翻譯環(huán)境 。

    接下來,我們用 gcc 分別演示這四個過程。

    1、預(yù)處理

    在預(yù)處理中,需要完成頭文件的展開、宏替換、去注釋、條件編譯等工作。

    經(jīng)過預(yù)處理后,當前文件還是 C 語言,只不過變得更加精簡。

    預(yù)處理指令 :

    gcc -E file.c -o file.i

    樣例程序 :

    進行預(yù)處理 :

    預(yù)處理之后生成 .i文件,分別打開 .c 和 .i 文件進行對比 :

    我們發(fā)現(xiàn)代碼變?yōu)榘税俣嘈校@是因為頭文件 # 被展開,同時預(yù)處理的其他過程也都進行了。

    2、編譯

    當程序在編譯時,gcc 會檢查代碼是否有語法錯誤,了解代碼基本內(nèi)容,檢查無誤就會把代碼翻譯為匯編語言。

    匯編語言中包含源文件的部分內(nèi)容,所以也可以說該文件為 C 語言匯編代碼 。

    編譯指令 :

    gcc -S myfile.i -o myfile.s

    通過源文件 .c 也可以形成編譯后的文件,指令為 gcc -s .c -o .s,但是我們?yōu)榱搜菔具^程的連續(xù)性,我們統(tǒng)一從上次生成的文件開始執(zhí)行指令。

    進行編譯 :

    觀察 .s 文件內(nèi)容:

    語句含有 c 語言的樣子;而下部分框起來的語句則是匯編代碼,由此證明在編譯過后生成的文件為 C 語言匯編代碼。

    3、匯編

    匯編之后會把匯編語言轉(zhuǎn)換為二進制文件。

    這里的二進制文件可以說是 可重定位二進制文件 。該文件不能被執(zhí)行,類似于 上的 .obj 文件。

    這一步知識把我們自己的代碼翻譯為二進制目標文件。

    由于機器只認識二進制文件,所以換言之,這一步就是把人能看懂的文件,翻譯成機器能看懂的,就是 生成機器可識別代碼 。

    匯編指令 :

    gcc -c myfile.s -o test.o

    進行匯編 :

    觀察.o 內(nèi)容:

    打開文件發(fā)現(xiàn)什么都看不懂。

    這就是二進制文件,計算機可以識別該文件。

    那么該文件可以執(zhí)行嗎?

    不可以執(zhí)行,報錯信息為權(quán)限被拒絕,通常為權(quán)限不夠。那這怎么證明該文件不能執(zhí)行?

    我們將其提權(quán)試試:

    然后再次 ./.o 執(zhí)行該文件:

    仍然執(zhí)行失敗,并報錯:無法執(zhí)行該二進制文件。所以這就證明我們的結(jié)論:匯編生成的二進制文件不可執(zhí)行!

    4、鏈接

    鏈接過程就是將程序和對應(yīng)的庫鏈接起來,編譯器會自動識別語言。

    鏈接指令 :

    gcc myfile.o -o myfile

    進行鏈接 :

    再執(zhí)行生成的可執(zhí)行程序 :

    5、總結(jié)

    我們這邊將翻譯過程按步執(zhí)行只是為了讓小伙伴們理解程序由源代碼到可執(zhí)行程序的一個過程。

    實際上,在我們?nèi)粘>幾g代碼只需要 gcc .c 就可以一步生成可執(zhí)行文件。

    再提供一個記憶方式:

    對于 預(yù)處理、編譯、匯編 三步的選項分別為 ESc ,可以與鍵盤上的 esc 鍵來幫助記憶,區(qū)別前兩個字母是大寫。而生成的文件后綴分別為 iso 可以利用國際標準化組織(ISO)來記憶。

    二、動靜態(tài)鏈接庫 1、庫的認識

    首先清楚一點,我們寫的代碼里面經(jīng)常會用庫函數(shù),這些調(diào)用接口的方式是我們寫的,但是這些庫函數(shù)的底層實現(xiàn)不是我們寫的,而這中間就有一個調(diào)用庫的過程。

    在鏈接的過程中,需要對形成的二進制文件和庫文件進行合并從而形成可執(zhí)行程序,這邊就調(diào)用了庫。庫是能成功編譯的必要條件。

    我們一直在使用庫,至少是語言上的庫。

    比如上方鏈接生成的可執(zhí)行程序 file ,它就依賴了庫。

    通過 ldd ,就可以查看該程序依賴了哪些庫:

    不僅程序依賴庫,我們在 linux 下能進行代碼編寫也是因為內(nèi)置了庫。linux 默認有語言級別的頭文件,和語言對應(yīng)的庫。

    通過 ls /usr// 就可以看到系統(tǒng)的內(nèi)置的頭文件,我們通過頭文件就可以根據(jù)庫函數(shù),找到對應(yīng)的方法,從而鏈接到正確的庫:

    在linux 下,庫分兩種 :

    靜態(tài)庫,格式為 .a 。

    動態(tài)庫,格式為 .so 。

    基于上面的格式,不同的庫還可能會有版本,例如 程序就依賴了libc.so.6 ,后面的 .6 就是版本:

    并且我們發(fā)現(xiàn)可執(zhí)行程序依賴的就是 .so 動態(tài)庫。

    對于動靜態(tài)庫,以lib 為前綴,.a/.so 為后綴,掐頭去尾就是名稱。例如 libc.so.6 ,它的名字就是 c ,是 c 語言內(nèi)置庫。

    而以上動靜態(tài)庫的后綴為 linux 上特有的后綴劃分;如果是 下靜態(tài)庫為 lib ,動態(tài)庫為 dll 。

    不止可執(zhí)行程序,就連指令也依賴于庫,我們觀察幾個指令:

    常用的 ls, tar 它們都依賴于庫,甚至還依賴于 c 庫。

    由此發(fā)現(xiàn),指令和 c 程序一樣,都依賴與庫。所以我們可以將指令看待為:指令是程序,是工具,也是“指令(字面意思)” 。

    雖然從編譯角度來說,指令和我們寫的 c 程序沒有任何區(qū)別,但是從功能上來說確是天差地別。

    講了這么多c標準庫有靜態(tài)和動態(tài)庫,實際上也就是一句話,庫是必要的,并且?guī)旆譃閯討B(tài)庫和靜態(tài)庫 。

    2、鏈接方式

    Linux 的鏈接方式就兩種:

    而 Linux 默認的鏈接方式為 動態(tài)鏈接 ,我們來證明一下:

    用 指令查看 文件的類型:

    我們發(fā)現(xiàn)生成的可執(zhí)行程序默認就是采用的 動態(tài)鏈接 。

    那么為什么采用靜態(tài)鏈接而不采用動態(tài)鏈接?這里面有什么原因?

    我們先了解一下動靜態(tài)庫。

    3、動態(tài)庫與靜態(tài)庫

    動態(tài)庫對應(yīng)的鏈接方式為動態(tài)鏈接;靜態(tài)庫對應(yīng)的鏈接方式為靜態(tài)鏈接。

    動態(tài)鏈接必須使用動態(tài)庫,靜態(tài)鏈接必須使用靜態(tài)庫。

    動態(tài)庫優(yōu)缺點:

    動態(tài)庫也可以說是共享庫。動態(tài)庫在鏈接的時候,并沒有把相應(yīng)的庫文件加載到可執(zhí)行程序中,而是在運行的時候,拷貝庫中所需代碼的地址到可執(zhí)行程序中相關(guān)的位置。

    通過這種鏈接方式,使用動態(tài)庫就大大節(jié)省了內(nèi)存損耗。

    但是這也帶來一個缺點,由于動態(tài)庫鏈接時,是通過地址鏈接的。所以只要我們的動態(tài)庫缺失,程序便無法運行。

    靜態(tài)庫優(yōu)缺點:

    靜態(tài)庫則是在編譯鏈接時c標準庫有靜態(tài)和動態(tài)庫,把庫文件的代碼全部加載到可執(zhí)行程序中。

    這種鏈接方式導(dǎo)致生成文件體積龐大。若文件數(shù)目一多,到時候內(nèi)存就會被占用很多。

    但是這也有一個優(yōu)點,這樣就使得程序不依賴于庫了。即使庫出了問題,也沒事,因為我們已經(jīng)將代碼加載到程序中了。

    通過上面,我們發(fā)現(xiàn),動態(tài)庫可以大大節(jié)省內(nèi)存開銷,并且一般對應(yīng)的動態(tài)庫并不會出問題,再衡量可執(zhí)行程序很多的情況,動態(tài)鏈接其實是最好的鏈接方式。

    所以 Linux 默認是采用動態(tài)鏈接的鏈接方式。

    4、兩種鏈接方式的使用

    對于動態(tài)鏈接,我們已經(jīng)使用過了,比如上文生成的 文件,就是動態(tài)鏈接生成的。

    而靜態(tài)鏈接則需要通過特定方式來使用,并且 Linux 默認只裝了動態(tài)庫,靜態(tài)庫是沒裝的,所以先安裝一下:

    sudo yum install -y glibc-static

    安裝完畢后,就可以使用了。

    靜態(tài)鏈接的使用方式為:

    gcc  myfile.c -o myfile-static -static

    我們發(fā)現(xiàn),靜態(tài)鏈接后生成的可執(zhí)行程序的體積非常大。

    再用 file - 查看一下文件類型:

    就變成 :靜態(tài)鏈接了。

    三、gcc 選項匯總

    gcc 常用的選項和操作也就是 -o 選項還有 gcc file 直接生成可執(zhí)行程序。

    下面對其他選項做出一些補充:

    -E :只激活預(yù)處理,這個不生成文件,你需要把它重定向到一個輸出文件里面

    -S :編譯到匯編語言不進行匯編和鏈接

    -c :編譯到目標代碼

    -o :文件輸出到文件

    - :此選項對生成的文件采用靜態(tài)鏈接

    -g :生成調(diào)試信息。GNU 調(diào)試器可利用該信息

    - :此選項將盡量使用動態(tài)庫,所以生成文件比較小,但是需要系統(tǒng)由動態(tài)庫

    -O0 :不做任何優(yōu)化,這是默認的編譯選項。

    -O1 : 對程序做部分編譯優(yōu)化

    -O2 :是比O1更高級的選項,進行更多的優(yōu)化

    -O3 :比O2更進一步的進行優(yōu)化

    -w :不生成任何警告信息

    -Wall: 生成所有警告信息

網(wǎng)站首頁   |    關(guān)于我們   |    公司新聞   |    產(chǎn)品方案   |    用戶案例   |    售后服務(wù)   |    合作伙伴   |    人才招聘   |   

友情鏈接: 餐飲加盟

地址:北京市海淀區(qū)    電話:010-     郵箱:@126.com

備案號:冀ICP備2024067069號-3 北京科技有限公司版權(quán)所有