Liinux編譯器gcc/g++
1.背景知識(shí)(程序的翻譯)
以gcc編譯
以g++編譯,但是此時(shí)會(huì)發(fā)現(xiàn)沒(méi)有g(shù)++這個(gè)指令,所有需要安裝它,安裝指令yum install gcc gcc-c++
gcc和g++都會(huì)形成可執(zhí)行文件a.out
gcc只能編譯c語(yǔ)言代碼,g++能編譯c/c++
以c程序?yàn)槔?,?lái)看看它從一個(gè)文本類的c程序編譯成計(jì)算機(jī)可以認(rèn)識(shí)的二進(jìn)制程序它需要經(jīng)過(guò)四個(gè)階段
預(yù)處理
編譯
匯編
連接
每個(gè)階段要做什么?
預(yù)處理
預(yù)處理階段會(huì)做
1.去注釋
2.頭文件展開
3.條件編譯
4.宏的替換
編寫一個(gè)c程序,其中有宏、頭文件、注釋
而gcc它預(yù)處理階段所需的選項(xiàng)是-E
-E后面跟的是編寫的文件,然后-o是生成目標(biāo)文件,可以自己指定生成文件名
然后再打開文件將這兩個(gè)文件一對(duì)比
預(yù)處理之后mycode這個(gè)文件里面的內(nèi)容較于mycode.c文件多了太多內(nèi)容了
從開始行一直往下翻,直到int main,它多了這些內(nèi)容都是從頭文件中拷貝過(guò)來(lái)的,而這個(gè)行為是頭文件的展開
它多出了這么多內(nèi)容是從頭文件中拷貝過(guò)來(lái)的,那么這個(gè)頭文件又是從哪來(lái),其實(shí)在你安裝編寫c/c++或者其它語(yǔ)言的環(huán)境時(shí),不僅僅是安裝了軟件,還將其所需的頭文件庫(kù)文件等內(nèi)容也一并安裝了,頭文件頭文件他也是文件對(duì)吧!來(lái)看看頭文件存在系統(tǒng)哪里
一般開發(fā)所需的頭文件它是在/usr/include/
這個(gè)路徑下
這個(gè)路徑是Linux下gcc/g++它的頭文件的搜索路徑
如打開stdio.h這個(gè)頭文件
它里面有很多內(nèi)容
所有我們?cè)诎惭b如vs2022之類的開發(fā)環(huán)境之外,還安裝了對(duì)應(yīng)的開發(fā)包!同步也在下載了c/c++的頭文件
而其中宏定義的M,經(jīng)過(guò)預(yù)處理之后進(jìn)行了值替換
注釋也去掉了
條件編譯
它是以宏的方式定義DEBUG,它是如果存在這個(gè),那么就輸出 printf(“hello\n”);
沒(méi)有保留printf(“xiao\n”);,他這是選擇!
在預(yù)處理之后編譯器繼續(xù)運(yùn)行形成匯編!這個(gè)階段叫做編譯
編譯
編譯會(huì)將代碼形成匯編gcc -S mycode.c -o mycode.s
匯編,是 -S
選項(xiàng),后面跟源文件,-o 匯編成目標(biāo)文件,一般以.s為后綴
vim打開mycode.s文件,會(huì)發(fā)現(xiàn)里面都是匯編代碼
形成匯編代碼之后再經(jīng)過(guò)匯編階段形成機(jī)器可以識(shí)別的二進(jìn)制碼
匯編
它匯編階段的選項(xiàng)是-c
演示匯編階段 gcc -c mycode.s -o mycode.o
當(dāng)以vim打開這個(gè)文件,全是亂碼,這是因?yàn)樗且粋€(gè)文本編輯器,要以專門看二進(jìn)制文件的。
以od這個(gè)工具查看
匯編之后再經(jīng)過(guò)連接形成可執(zhí)行文件。
連接
直接gcc編譯不用再跟選項(xiàng),gcc mycode.i -o mytest
它會(huì)形成可執(zhí)行文件
-o后面緊跟著你要形成的文件名,自定義的!如果不加,那么它會(huì)形成a,out
-E:預(yù)處理!對(duì)程序進(jìn)行翻譯,將預(yù)處理工作做完就停下來(lái),再執(zhí)行就是編譯了
-S:編譯!將c語(yǔ)言代碼翻譯成匯編代碼,編譯工作做完之后就停下來(lái),再執(zhí)行就是匯編
-c:匯編!將匯編代碼翻譯成機(jī)器可識(shí)別的二進(jìn)制碼,它生成可重定向的二進(jìn)制文件
2.動(dòng)態(tài)庫(kù)、靜態(tài)庫(kù)
連接:將二進(jìn)制文件與庫(kù)進(jìn)行鏈接形成可執(zhí)行程序
鏈接它的庫(kù)是啥作用?這個(gè)庫(kù)給我們提供方法,他其實(shí)就是c語(yǔ)言的標(biāo)準(zhǔn)庫(kù),那么它在哪存在?
存在:/usr/lib64之下,
此時(shí)只看見(jiàn)有動(dòng)態(tài)庫(kù),等會(huì)安裝靜態(tài)庫(kù)
靜態(tài)庫(kù)安裝
安裝C語(yǔ)言靜態(tài)庫(kù)yum -y install glibc-static
安裝c++靜態(tài)庫(kù) yum -y install libstdc++-static
c語(yǔ)言的標(biāo)準(zhǔn)庫(kù)本質(zhì)上是一個(gè)文件,庫(kù)分兩種,Linux下:動(dòng)態(tài)庫(kù)(.so),靜態(tài)庫(kù)(.a)
windows:動(dòng)態(tài)庫(kù)(.dll),靜態(tài)庫(kù)(.lib)
而庫(kù)一般有自己的命名規(guī)則的:libname.so.xxx
有了頭文件有了庫(kù)文件,它方法的實(shí)現(xiàn)也是再庫(kù)中實(shí)現(xiàn),它是把源文件經(jīng)過(guò)一定的翻譯,然后打包,只提供一個(gè)文件,這樣也可以達(dá)到隱藏文件的目的
頭文件提供方法的聲明,庫(kù)文件提供方法的實(shí)現(xiàn),加上寫的代碼就成為一個(gè)軟件了
gcc自動(dòng)去找c語(yǔ)言庫(kù)中找與.o文件鏈接形成可執(zhí)行文件!那它們是如何鏈接的?
兩種鏈接方案:動(dòng)態(tài)鏈接;靜態(tài)鏈接!
動(dòng)態(tài)鏈接:就相當(dāng)于高中,學(xué)校旁邊哪哪哪有一個(gè)網(wǎng)吧,然后學(xué)生周天去上網(wǎng),學(xué)生在執(zhí)行著各種活動(dòng),然后忽然想去上網(wǎng),它他在學(xué)校是上不了的,因?yàn)樗麤](méi)有電腦,所有他跑去網(wǎng)吧上網(wǎng),打游戲!這個(gè)網(wǎng)吧就相當(dāng)于動(dòng)態(tài)庫(kù),每次想上網(wǎng)都要去網(wǎng)吧登機(jī)才行,這種鏈接方式就叫做動(dòng)態(tài)鏈接!而網(wǎng)吧上網(wǎng)不可能只有你一個(gè)人吧,有很多人去,他是共享的,動(dòng)態(tài)庫(kù)是共享的,這所學(xué)校的所有學(xué)生要上網(wǎng)都去這個(gè)網(wǎng)吧去!
而當(dāng)這個(gè)網(wǎng)吧倒閉之后,這所學(xué)校的學(xué)生就不能去上網(wǎng)了,真慘?。?br> 所有動(dòng)態(tài)庫(kù)不能缺失,一旦一個(gè)動(dòng)態(tài)庫(kù)缺失,可能很多程序都無(wú)法運(yùn)行,不然會(huì)讓很多程序都無(wú)法跑起來(lái)!
查看一個(gè)可執(zhí)行程序依賴的動(dòng)態(tài)庫(kù)
ldd指令
如果刪掉了這個(gè)動(dòng)態(tài)庫(kù)文件他就跑不起來(lái)了!不要?jiǎng)h,不然可能不止他一個(gè)程序跑不起來(lái),可能會(huì)很多都跑不起來(lái),因?yàn)長(zhǎng)inux很多指令都是用c語(yǔ)言實(shí)現(xiàn)的,如果你刪了,可能很多指令也不能執(zhí)行噢!
靜態(tài)鏈接:將庫(kù)中的方法拷貝到自己程序中,他每次要用的時(shí)候不用再去庫(kù)中,自己就能實(shí)現(xiàn),這樣的方式就叫做靜態(tài)鏈接!如果有一天他的方法所在庫(kù)不在了他還是可以照樣運(yùn)行!它不再依賴于這個(gè)庫(kù)了,它將所有方法都拷貝到這個(gè)程序中!
動(dòng)態(tài)鏈接是將方法實(shí)現(xiàn)在哪里拷貝到程序中,每次要連接時(shí)都要去動(dòng)態(tài)庫(kù)中,靜態(tài)連接是將方法實(shí)現(xiàn)拷貝到程序中,每次要時(shí)不必去靜態(tài)庫(kù)中連接!但是靜態(tài)連接會(huì)使程序變大,因?yàn)樗截惲烁嗟臇|西!
在Linux中默認(rèn)采用的就是動(dòng)態(tài)鏈接!使用動(dòng)態(tài)庫(kù)!
而如果當(dāng)想要使用靜態(tài)鏈接要在編譯時(shí)要加-static選項(xiàng)。靜態(tài)鏈接是需要手動(dòng)添加選項(xiàng)的。此時(shí)也就要求系統(tǒng)提供靜態(tài)庫(kù)。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-495784.html
而靜態(tài)鏈接可以發(fā)現(xiàn)它的體積遠(yuǎn)大于動(dòng)態(tài)鏈接方式!
如果沒(méi)有靜態(tài)庫(kù)是不能使用靜態(tài)鏈接方式的,但是如果沒(méi)有動(dòng)態(tài)庫(kù),只有靜態(tài)庫(kù),并且能夠找到,這是可以的,就算沒(méi)有使用static也可以因?yàn)間cc默認(rèn)鏈接是動(dòng)態(tài)如果沒(méi)有會(huì)用靜態(tài)鏈接!其實(shí)使用static是改變鏈接優(yōu)先級(jí)了,所以啊,一個(gè)可執(zhí)行程序,為其提供的庫(kù)可能不止一個(gè)偶,可能動(dòng)態(tài)靜態(tài)都有!
來(lái)動(dòng)靜態(tài)庫(kù)比一比
動(dòng)態(tài)vs靜態(tài)
動(dòng)態(tài)庫(kù)是共享庫(kù),可以有效的節(jié)省資源(磁盤、網(wǎng)絡(luò)、內(nèi)存空間)缺點(diǎn):動(dòng)態(tài)庫(kù)不可缺失,一旦缺失導(dǎo)致很多程序無(wú)法運(yùn)行
靜態(tài)庫(kù)不依賴庫(kù),程序可以獨(dú)立運(yùn)行。缺點(diǎn):占用體積大,比較消耗資源!
debug和release
在vs下程序有兩種開發(fā)方式debug和release方式,平時(shí)用的就是debug方式,當(dāng)代碼需要提測(cè)測(cè)試時(shí)要將其以release的方式發(fā)布!測(cè)試發(fā)布的版本和用戶拿到的時(shí)一樣的,默認(rèn)發(fā)布為release,而以debug形成的可執(zhí)行程序可以被追蹤,為何?因?yàn)樗砑恿丝烧{(diào)試信息
而由于它添加了調(diào)試信息,它形成的可執(zhí)行程序的體積又要比一般程序的大
還說(shuō)一個(gè)選項(xiàng) -g選項(xiàng),它會(huì)將軟件以debug方式發(fā)布,
那么如何去看是否是debug方式發(fā)布呢,可以使用readelf -S來(lái)查看
它會(huì)以二進(jìn)制方式查看,然后可以grep debug過(guò)濾
這些也就是添加的debug信息!
g++也是一樣的,就不再演示了!
??就到這了!文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-495784.html
到了這里,關(guān)于Linux編譯器gcc/g++的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!