日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁 > 智能硬件 > 智能硬件
[導(dǎo)讀]自學(xué)c編譯器的朋友都知道。c編譯器作為常用軟件之一,并非具備無法逾越難度。對于c編譯器的學(xué)習(xí),往往需要具備一定耐心。本文對c編譯器的講解基于gcc c編譯器,同時(shí)本文承接“c編譯器so easy,gcc c編譯器生成、使用動(dòng)靜態(tài)庫(上篇)”一文而談,不了解的朋友可以先回顧一番哦。

自學(xué)c編譯器的朋友都知道。c編譯器作為常用軟件之一,并非具備無法逾越難度。對于c編譯器的學(xué)習(xí),往往需要具備一定耐心。本文對c編譯器的講解基于gcc c編譯器,同時(shí)本文承接“c編譯器so easy,gcc c編譯器生成、使用動(dòng)靜態(tài)庫(上篇)”一文而談,不了解的朋友可以先回顧一番哦。此外,本文主要內(nèi)容為gcc生成靜態(tài)和動(dòng)態(tài)鏈接庫的示例,一起來了解下吧。

我們通常把一些公用函數(shù)制作成函數(shù)庫,供其它程序使用。函數(shù)庫分為靜態(tài)庫和動(dòng)態(tài)庫兩種。

靜態(tài)庫在程序編譯時(shí)會(huì)被連接到目標(biāo)代碼中,程序運(yùn)行時(shí)將不再需要該靜態(tài)庫。

動(dòng)態(tài)庫在程序編譯時(shí)并不會(huì)被連接到目標(biāo)代碼中,而是在程序運(yùn)行是才被載入,因此在程序運(yùn)行時(shí)還需要?jiǎng)討B(tài)庫存在。

本文主要通過舉例來說明在Linux中如何創(chuàng)建靜態(tài)庫和動(dòng)態(tài)庫,以及使用它們。

為了便于闡述,我們先做一部分準(zhǔn)備工作。

1.準(zhǔn)備好測試代碼hello.h、hello.c和main.c

hello.h(見程序1)為該函數(shù)庫的頭文件。

hello.c(見程序2)是函數(shù)庫的源程序,其中包含公用函數(shù)hello,該函數(shù)將在屏幕上輸出“Hello XXX!”。

main.c(見程序3)為測試庫文件的主程序,在主程序中調(diào)用了公用函數(shù)hello。

程序1: hello.h

#ifndef HELLO_H

#define HELLO_H

void hello(const char *name);

#endif

程序2:hello.c#include

void hello(const char *name) {

printf(“Hello %s!\n”, name);

}

程序3:main.c#include “hello.h”

int main()

{

hello(“everyone”);

return 0;

}

2.問題的提出

注意:這個(gè)時(shí)候,我們編譯好的hello.o是無法通過gcc –o 編譯的,這個(gè)道理非常簡單,

hello.c是一個(gè)沒有main函數(shù)的.c程序,因此不夠成一個(gè)完整的程序,如果使用gcc –o 編譯并連接它,GCC將報(bào)錯(cuò)。

無論靜態(tài)庫,還是動(dòng)態(tài)庫,都是由.o文件創(chuàng)建的。因此,我們必須將源程序hello.c通過gcc先編譯成.o文件。

這個(gè)時(shí)候我們有三種思路:

1) 通過編譯多個(gè)源文件,直接將目標(biāo)代碼合成一個(gè).o文件。

2) 通過創(chuàng)建靜態(tài)鏈接庫libmyhello.a,使得main函數(shù)調(diào)用hello函數(shù)時(shí)可調(diào)用靜態(tài)鏈接庫。

3) 通過創(chuàng)建動(dòng)態(tài)鏈接庫libmyhello.so,使得main函數(shù)調(diào)用hello函數(shù)時(shí)可調(diào)用靜態(tài)鏈接庫。

3.思路一:編譯多個(gè)源文件

在系統(tǒng)提示符下鍵入以下命令得到hello.o文件。

# gcc -c hello.c

為什么不使用gcc–o hello hello.cpp 這個(gè)道理我們之前已經(jīng)說了,使用-c是什么意思呢?這涉及到gcc 編譯選項(xiàng)的常識(shí)。

我們通常使用的gcc –o 是將.c源文件編譯成為一個(gè)可執(zhí)行的二進(jìn)制代碼(-o選項(xiàng)其實(shí)是制定輸出文件文件名,如果不加-c選項(xiàng),gcc默認(rèn)會(huì)編譯連接生成可執(zhí)行文件,文件的名稱有-o選項(xiàng)指定),這包括調(diào)用作為GCC內(nèi)的一部分真正的C編譯器(ccl),以及調(diào)用GNU C編譯器的輸出中實(shí)際可執(zhí)行代碼的外部GNU匯編器(as)和連接器工具(ld)。

而gcc –c是使用GNU匯編器將源文件轉(zhuǎn)化為目標(biāo)代碼之后就結(jié)束,在這種情況下,只調(diào)用了C編譯器(ccl)和匯編器(as),而連接器(ld)并沒有被執(zhí)行,所以輸出的目標(biāo)文件不會(huì)包含作為Linux程序在被裝載和執(zhí)行時(shí)所必須的包含信息,但它可以在以后被連接到一個(gè)程序。

我們運(yùn)行l(wèi)s命令看看是否生存了hello.o文件。

# ls

hello.c hello.h hello.o main.c

在ls命令結(jié)果中,我們看到了hello.o文件,本步操作完成。

同理編譯main

#gcc –c main.c

將兩個(gè)文件鏈接成一個(gè).o文件。

#gcc –o hello hello.o main.o

運(yùn)行

# 。/hello

Hello everyone!

4.思路二:靜態(tài)鏈接庫

下面我們先來看看如何創(chuàng)建靜態(tài)庫,以及使用它。

靜態(tài)庫文件名的命名規(guī)范是以lib為前綴,緊接著跟靜態(tài)庫名,擴(kuò)展名為.a。例如:我們將創(chuàng)建的靜態(tài)庫名為myhello,則靜態(tài)庫文件名就是libmyhello.a。在創(chuàng)建和使用靜態(tài)庫時(shí),需要注意這點(diǎn)。創(chuàng)建靜態(tài)庫用ar命令。

在系統(tǒng)提示符下鍵入以下命令將創(chuàng)建靜態(tài)庫文件libmyhello.a。

# ar rcs libmyhello.a hello.o

我們同樣運(yùn)行l(wèi)s命令查看結(jié)果:

# ls

hello.c hello.h hello.o libmyhello.a main.c

ls命令結(jié)果中有l(wèi)ibmyhello.a。

靜態(tài)庫制作完了,如何使用它內(nèi)部的函數(shù)呢?只需要在使用到這些公用函數(shù)的源程序中包含這些公用函數(shù)的原型聲明,然后在用gcc命令生成目標(biāo)文件時(shí)指明靜態(tài)庫名,gcc將會(huì)從靜態(tài)庫中將公用函數(shù)連接到目標(biāo)文件中。注意,gcc會(huì)在靜態(tài)庫名前加上前綴lib,然后追加擴(kuò)展名.a得到的靜態(tài)庫文件名來查找靜態(tài)庫文件,因此,我們在寫需要連接的庫時(shí),只寫名字就可以,如libmyhello.a的庫,只寫:-lmyhello

在程序3:main.c中,我們包含了靜態(tài)庫的頭文件hello.h,然后在主程序main中直接調(diào)用公用函數(shù)hello。下面先生成目標(biāo)程序hello,然后運(yùn)行hello程序看看結(jié)果如何。

# gcc -o hello main.c -static -L. -lmyhello

# 。/hello

Hello everyone!

我們刪除靜態(tài)庫文件試試公用函數(shù)hello是否真的連接到目標(biāo)文件 hello中了。

# rm libmyhello.a

rm: remove regular file `libmyhello.a‘? y

# 。/hello

Hello everyone!

程序照常運(yùn)行,靜態(tài)庫中的公用函數(shù)已經(jīng)連接到目標(biāo)文件中了。

靜態(tài)鏈接庫的一個(gè)缺點(diǎn)是,如果我們同時(shí)運(yùn)行了許多程序,并且它們使用了同一個(gè)庫函數(shù),這樣,在內(nèi)存中會(huì)大量拷貝同一庫函數(shù)。這樣,就會(huì)浪費(fèi)很多珍貴的內(nèi)存和存儲(chǔ)空間。使用了共享鏈接庫的Linux就可以避免這個(gè)問題。

共享函數(shù)庫和靜態(tài)函數(shù)在同一個(gè)地方,只是后綴有所不同。比如,在一個(gè)典型的Linux系統(tǒng),標(biāo)準(zhǔn)的共享數(shù)序函數(shù)庫是/usr/lib/libm.so。

當(dāng)一個(gè)程序使用共享函數(shù)庫時(shí),在連接階段并不把函數(shù)代碼連接進(jìn)來,而只是鏈接函數(shù)的一個(gè)引用。當(dāng)最終的函數(shù)導(dǎo)入內(nèi)存開始真正執(zhí)行時(shí),函數(shù)引用被解析,共享函數(shù)庫的代碼才真正導(dǎo)入到內(nèi)存中。這樣,共享鏈接庫的函數(shù)就可以被許多程序同時(shí)共享,并且只需存儲(chǔ)一次就可以了。共享函數(shù)庫的另一個(gè)優(yōu)點(diǎn)是,它可以獨(dú)立更新,與調(diào)用它的函數(shù)毫不影響。

5.思路三、動(dòng)態(tài)鏈接庫(共享函數(shù)庫)

我們繼續(xù)看看如何在Linux中創(chuàng)建動(dòng)態(tài)庫。我們還是從.o文件開始。

動(dòng)態(tài)庫文件名命名規(guī)范和靜態(tài)庫文件名命名規(guī)范類似,也是在動(dòng)態(tài)庫名增加前綴lib,但其文件擴(kuò)展名為.so。例如:我們將創(chuàng)建的動(dòng)態(tài)庫名為myhello,則動(dòng)態(tài)庫文件名就是libmyhello.so。用gcc來創(chuàng)建動(dòng)態(tài)庫。

在系統(tǒng)提示符下鍵入以下命令得到動(dòng)態(tài)庫文件libmyhello.so。

# gcc -shared -fPIC -o libmyhello.so hello.o

“PIC”命令行標(biāo)記告訴GCC產(chǎn)生的代碼不要包含對函數(shù)和變量具體內(nèi)存位置的引用,這是因?yàn)楝F(xiàn)在還無法知道使用該消息代碼的應(yīng)用程序會(huì)將它連接到哪一段內(nèi)存地址空間。這樣編譯出的hello.o可以被用于建立共享鏈接庫。建立共享鏈接庫只需要用GCC的”-shared”標(biāo)記即可。

我們照樣使用ls命令看看動(dòng)態(tài)庫文件是否生成。

# ls

hello.cpp hello.h hello.o libmyhello.so main.cpp

調(diào)用動(dòng)態(tài)鏈接庫編譯目標(biāo)文件。

在程序中使用動(dòng)態(tài)庫和使用靜態(tài)庫完全一樣,也是在使用到這些公用函數(shù)的源程序中包含這些公用函數(shù)的原型聲明,然后在用gcc命令生成目標(biāo)文件時(shí)指明動(dòng)態(tài)庫名進(jìn)行編譯。我們先運(yùn)行g(shù)cc命令生成目標(biāo)文件,再運(yùn)行它看看結(jié)果。

如果直接用如下方法進(jìn)行編譯,并連接:

# gcc -o hello main.c -L. -lmyhello

(使用”-lmyhello”標(biāo)記來告訴GCC驅(qū)動(dòng)程序在連接階段引用共享函數(shù)庫libmyhello.so。”-L.”標(biāo)記告訴GCC函數(shù)庫可能位于當(dāng)前目錄。否則GNU連接器會(huì)查找標(biāo)準(zhǔn)系統(tǒng)函數(shù)目錄:它先后搜索1.elf文件的 DT_RPATH段—2.環(huán)境變量LD_LIBRARY_PATH—3./etc/ld.so.cache文件列表—4./lib/,/usr/lib目錄找到庫文件后將其載入內(nèi)存,但是我們生成的共享庫在當(dāng)前文件夾下,并沒有加到上述的4個(gè)路徑的任何一個(gè)中,因此,執(zhí)行后會(huì)出現(xiàn)錯(cuò)誤)

# 。/hello

。/hello: error while loading shared libraries: libmyhello.so: cannot open shared object file: No such file or directory

#

錯(cuò)誤提示,找不到動(dòng)態(tài)庫文件libmyhello.so。程序在運(yùn)行時(shí),會(huì)在/usr/lib和/lib等目錄中查找需要的動(dòng)態(tài)庫文件。若找到,則載入動(dòng)態(tài)庫,否則將提示類似上述錯(cuò)誤而終止程序運(yùn)行。有多種方法可以解決,

(1)我們將文件 libmyhello.so復(fù)制到目錄/usr/lib中,再試試。

# mv libmyhello.so /usr/lib

# 。/hello

成功!

(2)既然連接器會(huì)搜尋LD_LIBRARY_PATH所指定的目錄,那么我們可以將這個(gè)環(huán)境變量設(shè)置成當(dāng)前目錄:

先執(zhí)行:

export LD_LIBRARY_PATH=$(pwd)

再執(zhí)行:

。/hello

成功!

(3)執(zhí)行:

ldconfig /usr/zhsoft/lib

注: 當(dāng)用戶在某個(gè)目錄下面創(chuàng)建或拷貝了一個(gè)動(dòng)態(tài)鏈接庫,若想使其被系統(tǒng)共享,可以執(zhí)行一下“ldconfig 目錄名”這個(gè)命令。此命令的功能在于讓ldconfig將指定目錄下的動(dòng)態(tài)鏈接庫被系統(tǒng)共享起來,意即:在緩存文件/etc/ld.so.cache中追加進(jìn)指定目錄下的共享庫。本例讓系統(tǒng)共享了/usr/zhsoft/lib目錄下的動(dòng)態(tài)鏈接庫。該命令會(huì)重建/etc/ld.so.cache文件。

以上便是此次小編帶來的“c編譯器”相關(guān)內(nèi)容,通過本文,希望大家對gcc生成靜態(tài)和動(dòng)態(tài)鏈接庫的過程具備一定的了解。如果你喜歡本文,不妨持續(xù)關(guān)注我們網(wǎng)站哦,小編將于后期帶來更多精彩內(nèi)容。最后,十分感謝大家的閱讀,have a nice day!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

在windows平臺(tái)和linux平臺(tái)下都大量存在著庫。庫本質(zhì)上是可執(zhí)行代碼的二進(jìn)制形式,能夠被操作系統(tǒng)加載到內(nèi)存中并執(zhí)行。由于Windows和Linux的基本差異,所以這兩個(gè)平臺(tái)的庫二進(jìn)制文件不相容??梢院唵蔚乩斫鉃閷⑦@...

關(guān)鍵字: 動(dòng)態(tài)庫 靜態(tài)庫

如果你是在Linux下做開發(fā),你就必須知道Makefile是什么東西,如果不知道那就可以說你不是一個(gè)合格的Linux開發(fā)工程師,因?yàn)镸akefile是必備的一項(xiàng)技能。那么,Makefile到底有什么作用呢?首先,gcc大...

關(guān)鍵字: Linux Makefile gcc

眾所周知,LLVM的Clang C / C ++編譯器比GCC提供更快的編譯速度。 但是,新版本的GCC中的編譯速度有所提高。

關(guān)鍵字: gcc Linux llvm

上篇文章中,小編對Turbo c編譯器已做部分介紹。本文中,小編將對Turbo c編譯器余下內(nèi)容加以講解。如果你對c編譯器具有興趣,不妨繼續(xù)往下閱讀哦。

關(guān)鍵字: c編譯器 turbo 指數(shù)

為增進(jìn)大家對c編譯器的認(rèn)識(shí),本文將對Turbo C c編譯器予以講解。如果你對c編譯器具有興趣,不妨繼續(xù)往下閱讀哦。

關(guān)鍵字: c編譯器 turbo 指數(shù)

本文中,小編將對c編譯器和c編輯器的區(qū)別予以介紹。如果你對c編譯器具有興趣,不妨繼續(xù)往下閱讀哦。

關(guān)鍵字: c編譯器 指數(shù) c編輯器

最近發(fā)布的 GCC 10 編譯器已對 C++20 的主要功能協(xié)程(Co-Routines)進(jìn)行了初始支持,但是除非顯式地開啟該選項(xiàng),否則并不會(huì)啟用此功能。當(dāng) GCC 10 在 C++20 模式(std

關(guān)鍵字: gcc

許多朋友經(jīng)常混淆c編譯器和c編輯器,注意,c編譯器的作用在于編譯,而c編輯器在于編寫代碼。對于c編譯器,小編曾帶來諸多文章。但有網(wǎng)友提問,有沒有較為推薦的c編譯器。為解決大家的疑問,本文將對6款c編譯器予以介紹,大家可以...

關(guān)鍵字: c編譯器 指數(shù) 編譯器

c編譯器每天都在被使用,但對c編譯器十分了解的人卻不多,而對c編譯器編譯過程有所認(rèn)知的朋友更是少之又少。在上篇文章中,小編對c編譯器的工作過程有所講解。本文中,為繼續(xù)增進(jìn)大家對c編譯器的講解,將對編譯器工作過程的余下步驟...

關(guān)鍵字: c編譯器 指數(shù) 編譯器

c編譯器的問世是程序界的里程碑之一,沒有c編譯器,c程序?qū)o法運(yùn)行。由此可見,c編譯器尤為重要。為增進(jìn)大家對c編譯器的了解,本文將帶來c編譯器的通識(shí)篇,以使大家能夠了解編譯器的運(yùn)行過程。此外,本文僅為上篇,剩余內(nèi)容將在后...

關(guān)鍵字: c編譯器 指數(shù) 編譯器
關(guān)閉