C語言學習筆記_函式與函式庫
C語言學習筆記_函式與函式庫
函式庫
函式是模組化的,因此可以被複用。
函式庫就是一些事先寫好的函式的集合。
函式庫的提供形式:動態連結庫和靜態連結庫:
靜態連結庫
靜態庫是商業公司將自己的函式庫原始碼經過只編譯不連結形成的.o的目標檔案;
然後用ar工具將.o檔案歸檔成.a的歸檔檔案(.a的歸檔檔案又被稱為靜態連結庫檔案);
商業公司通過釋出.a庫檔案和.h標頭檔案來提供靜態庫給客戶使用;
客戶拿到,a和.h檔案後,通過標頭檔案中拿出被呼叫的那個函式的編譯後的.o二進位制程式碼連結進去形成最終的可執行程式;
靜態連結通過將庫中的程式碼連結進當前程式,優點是不依賴環境,在哪裡都能執行,缺點是程式將會非常大(因為庫函式也被連結進了程式中);
動態連結庫
動態連結庫比靜態出現的晚;
gcc編譯器預設使用動態連結,需要使用-static來強制靜態連結;
動態連結並不將庫中的程式碼連結程序序,只是做一個標記,當執行的時候再去載入。 優點是程式體積小佔用記憶體小,缺點是程式依賴環境,在庫檔案不存在時無法執行;
有多個應用程式都使用了庫函式時,動態連結庫就會很有優勢,因為這樣記憶體中的庫函式只有一份,不會重複載入;
字串處理函式
// TODO
數學庫函式
數學運算的函式定義在:/usr/include/i386-linux-gnu/bits/mathcalls.h
開平方函式:double sqrt(double x);
注意,需要在編譯時明確給出需要擴充套件的庫的名字,這是因為庫函式太多,聯結器在庫函式中搜索的時間會很長,為了提升連結速度,連結器只會去尋找幾個最常用的庫,所以不常用的庫被呼叫的時候需要給出擴充套件庫的名字;
連線時使用 -lxxx指示連結器去libxxx.so中搜索,本例中數學庫函式需要新增 -lm,表示連結到libm.so中;
製作靜態連結庫
靜態連結庫的字尾名是.a;
第一步,編寫原始檔和標頭檔案,假設命名為sp.c和sp.h;
第二步,編寫makefile檔案,makefile如下:
all:
gcc sp.c -o sp.o -c
ar -rc libsp.a sp.o
第一句的意思是隻編譯不連結,創建出sp.o,第二局的意思是利用ar命令將sp.o歸檔在libsp.a檔案中;
第三步,編寫test檔案測試此庫函式檔案是否有效,makefile檔案如下:
all: gcc test.c -o test -lsp -L.
其中,-lsp表示指定庫函式為sp,-L.表示指定庫函式的路徑為當前路徑(”.“表示當前路徑);
最後nm命令可以檢查歸檔檔案.a中有哪些.o檔案,分別有什麼函式;
製作動態連結庫
動態連結庫的字尾名為.so,對應於windwos下是dll;
第一步,編寫原始檔和標頭檔案,假設命名為sp.c和sp.h;
第二步,編寫makefile檔案如下:
all:
gcc sp.c -o sp.o -c -fPIC
gcc -o libsp.so sp.o -shared
-fPIC是位置無關碼,-shared表示以共享庫的方式來連結;
第三步,編寫test檔案測試此庫函式是否有效,
all:
gcc test.c -o test -lsp -L.
由於動態連結庫並沒有真正的連結源函式,所以此時執行並不能成功,需要第四步:
第四步,將libsp.so放到系統的固定目錄下:/usr/lib目錄;由於此目錄一般放重要的庫函式,所以不推薦此方法,可以考慮第五步的環境變數;
第五步,使用環境變數LD_LIBRARY_PATH,作業系統在載入固定目錄/usr/lib之前,會去LD_LIBRARY_PATH這個環境變數所指定的目錄下去尋找,如果找到就不用去固定目錄下找了,否則再去固定目錄/usr/lib中;
因此可以將製作的動態連結庫所在目錄新增進環境變數:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/sky/usr/lib
此時即可執行;
ldd命令
此命令的作用是在一個使用了共享庫的程式執行之前解析出這個程式使用了哪些共享庫,並檢視這些共享庫是否能被找到;