操屁眼的视频在线免费看,日本在线综合一区二区,久久在线观看免费视频,欧美日韩精品久久综

新聞資訊

    文章目錄

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

    二、動(dòng)靜態(tài)鏈接庫(kù)

    三、gcc 選項(xiàng)匯總

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

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

    在 Linux 中,C 語(yǔ)言用 gcc 編譯;C++ 用 g++ 編譯。

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

    接下來(lái),我們用 gcc 分別演示這四個(gè)過(guò)程。

    1、預(yù)處理

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

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

    預(yù)處理指令 :

    gcc -E file.c -o file.i

    樣例程序 :

    進(jìn)行預(yù)處理 :

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

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

    2、編譯

    當(dāng)程序在編譯時(shí),gcc 會(huì)檢查代碼是否有語(yǔ)法錯(cuò)誤,了解代碼基本內(nèi)容,檢查無(wú)誤就會(huì)把代碼翻譯為匯編語(yǔ)言。

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

    編譯指令 :

    gcc -S myfile.i -o myfile.s

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

    進(jìn)行編譯 :

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

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

    3、匯編

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

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

    這一步知識(shí)把我們自己的代碼翻譯為二進(jìn)制目標(biāo)文件。

    由于機(jī)器只認(rèn)識(shí)二進(jìn)制文件,所以換言之,這一步就是把人能看懂的文件,翻譯成機(jī)器能看懂的,就是 生成機(jī)器可識(shí)別代碼 。

    匯編指令 :

    gcc -c myfile.s -o test.o

    進(jìn)行匯編 :

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

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

    這就是二進(jìn)制文件,計(jì)算機(jī)可以識(shí)別該文件。

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

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

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

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

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

    4、鏈接

    鏈接過(guò)程就是將程序和對(duì)應(yīng)的庫(kù)鏈接起來(lái),編譯器會(huì)自動(dòng)識(shí)別語(yǔ)言。

    鏈接指令 :

    gcc myfile.o -o myfile

    進(jìn)行鏈接 :

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

    5、總結(jié)

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

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

    再提供一個(gè)記憶方式:

    對(duì)于 預(yù)處理、編譯、匯編 三步的選項(xiàng)分別為 ESc ,可以與鍵盤上的 esc 鍵來(lái)幫助記憶,區(qū)別前兩個(gè)字母是大寫(xiě)。而生成的文件后綴分別為 iso 可以利用國(guó)際標(biāo)準(zhǔn)化組織(ISO)來(lái)記憶。

    二、動(dòng)靜態(tài)鏈接庫(kù) 1、庫(kù)的認(rèn)識(shí)

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

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

    我們一直在使用庫(kù),至少是語(yǔ)言上的庫(kù)。

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

    通過(guò) ldd ,就可以查看該程序依賴了哪些庫(kù):

    不僅程序依賴庫(kù),我們?cè)?linux 下能進(jìn)行代碼編寫(xiě)也是因?yàn)閮?nèi)置了庫(kù)。linux 默認(rèn)有語(yǔ)言級(jí)別的頭文件,和語(yǔ)言對(duì)應(yīng)的庫(kù)。

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

    在linux 下,庫(kù)分兩種 :

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

    動(dòng)態(tài)庫(kù),格式為 .so 。

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

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

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

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

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

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

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

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

    講了這么多c標(biāo)準(zhǔn)庫(kù)有靜態(tài)和動(dòng)態(tài)庫(kù),實(shí)際上也就是一句話,庫(kù)是必要的,并且?guī)旆譃閯?dòng)態(tài)庫(kù)和靜態(tài)庫(kù) 。

    2、鏈接方式

    Linux 的鏈接方式就兩種:

    而 Linux 默認(rèn)的鏈接方式為 動(dòng)態(tài)鏈接 ,我們來(lái)證明一下:

    用 指令查看 文件的類型:

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

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

    我們先了解一下動(dòng)靜態(tài)庫(kù)。

    3、動(dòng)態(tài)庫(kù)與靜態(tài)庫(kù)

    動(dòng)態(tài)庫(kù)對(duì)應(yīng)的鏈接方式為動(dòng)態(tài)鏈接;靜態(tài)庫(kù)對(duì)應(yīng)的鏈接方式為靜態(tài)鏈接。

    動(dòng)態(tài)鏈接必須使用動(dòng)態(tài)庫(kù),靜態(tài)鏈接必須使用靜態(tài)庫(kù)。

    動(dòng)態(tài)庫(kù)優(yōu)缺點(diǎn):

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

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

    但是這也帶來(lái)一個(gè)缺點(diǎn),由于動(dòng)態(tài)庫(kù)鏈接時(shí),是通過(guò)地址鏈接的。所以只要我們的動(dòng)態(tài)庫(kù)缺失,程序便無(wú)法運(yùn)行。

    靜態(tài)庫(kù)優(yōu)缺點(diǎn):

    靜態(tài)庫(kù)則是在編譯鏈接時(shí)c標(biāo)準(zhǔn)庫(kù)有靜態(tài)和動(dòng)態(tài)庫(kù),把庫(kù)文件的代碼全部加載到可執(zhí)行程序中。

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

    但是這也有一個(gè)優(yōu)點(diǎn),這樣就使得程序不依賴于庫(kù)了。即使庫(kù)出了問(wèn)題,也沒(méi)事,因?yàn)槲覀円呀?jīng)將代碼加載到程序中了。

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

    所以 Linux 默認(rèn)是采用動(dòng)態(tài)鏈接的鏈接方式。

    4、兩種鏈接方式的使用

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

    而靜態(tài)鏈接則需要通過(guò)特定方式來(lái)使用,并且 Linux 默認(rèn)只裝了動(dòng)態(tài)庫(kù),靜態(tài)庫(kù)是沒(mé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 選項(xiàng)匯總

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

    下面對(duì)其他選項(xiàng)做出一些補(bǔ)充:

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

    -S :編譯到匯編語(yǔ)言不進(jìn)行匯編和鏈接

    -c :編譯到目標(biāo)代碼

    -o :文件輸出到文件

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

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

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

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

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

    -O2 :是比O1更高級(jí)的選項(xiàng),進(jìn)行更多的優(yōu)化

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

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

    -Wall: 生成所有警告信息

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

友情鏈接: 餐飲加盟

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

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