首先說明庫檔案與頭檔案在gcc中的具體使用方法,然後說明兩者的差別與聯系。
庫檔案即庫函數,如printf和scanf函數。以libgtdf.so庫檔案為例(庫檔案在命名時都以lib開頭,是以使用-l選項去連結指定的庫檔案時可以省略lib三個字母,即-lgtdf),一般庫檔案如果是放在/lib,/usr/lib,/usr/local/lib目錄(庫檔案的預設目錄)下,則無需額外處理,編譯連結時-lgtdf會自動找到對應檔案不會報錯,但是如果不在對應目錄,則需要加上-L 所在目錄 -lgtdf才能找到對應的庫檔案。頭檔案一般是采用源檔案中用#include指令包含,頭檔案如果放在/usr/include目錄下則會自動找到不會報錯,否則編譯連結時需要使用-I 所在目錄才能正确找到。頭檔案不需要具體指定是哪個頭檔案,因為在源代碼檔案中#include已經有說明,是以隻需要-I參數指明目錄即可,但是庫檔案需要-l參數指定是哪個庫檔案。例如:g++ test.cpp -o test.txt -L /mytest/lib -lgtdf -I /mytest/include 也等價于: gcc -lstdc++ test.cpp -o test.txt -L /mytest/lib -lgtdf -I /mytest/include 即gcc在編譯C++檔案時需要加上-lstdc++參數,具體原因可以參考之前的文章。
#include< > 與 #include“ ” 的差別:尖括号為系統标準庫頭檔案,會自動在/usr/include目錄下查找,引号為使用者自己定義的頭檔案,在未指定目錄的情況下,會先在目前工作目錄内查找,目前工作目錄找不到再在/usr/include目錄下查找。-I指定目錄時,先在指定目錄和目前工作目錄查找,然後在/usr/include目錄下查找。
Linux下的庫檔案分為兩大類,分别為動态連結庫(.so)和靜态連結庫(.a),兩者的差别僅在于程式執行時所需要的代碼是在運作時動态加載的,還是編譯時靜态加載的。預設情況下,gcc在連結時優先使用動态連結庫,隻有在動态連結庫不存在時,才會使用靜态連結庫。如果需要的話,可以在編譯時加上-static選項,強制使用靜态連結庫。如在/home/zsx/lib目錄内部由libfoo.so 和libfoo.a檔案,為了讓gcc隻用到靜态連結庫,而不使用動态連結庫,則可以:gcc foo.c -L /home/zsx/lib -static -lfoo -o foo ldd指令用來顯示二進制代碼檔案動态庫的連結情況,如:ldd foo
頭檔案是文本檔案,是可供閱讀的;庫檔案是二進制檔案,不可直接閱讀。庫檔案是将一系列的源檔案進行編譯打包,形成的二進制檔案包,其中封裝着函數接口,在程式設計中可以由其它源檔案調用。庫檔案可分為靜态庫和動态庫兩種。
頭檔案在編譯中使用;庫檔案在連結中使用。頭檔案中是函數或定義的聲明,及少量内聯函數的使用,一般不包含非靜态函數實作;庫檔案中包含函數的實作。頭檔案是手動編寫的,庫檔案是編譯生成的。
雖然沒有規定調用庫函數必須引用頭檔案,但一般約定,當調用庫函數的時候需要引用接口函數所在的頭檔案。
一個庫檔案均有一組頭檔案與其對應。庫檔案和對應頭檔案的作者應為同一個。作者必須保證頭檔案中所聲明的函數類型及參數清單,與庫檔案中的實作是相同的。
具體來說,頭檔案中有函數的申明,庫檔案實作函數的定義。比如,printf函數。使用時應包括stdio.h,打開stdio.h你隻能看到,printf這個函數的申明,卻看不到printf具體是怎麼實作的,而函數的實作在相應的C庫中。而庫檔案一般是以二進制形式而不是C源檔案形式提供給使用者使用的。程式中包括了stdio.h這個頭檔案。連結器就能根據頭件中的資訊找到printf這個函數的實作并連結進這個程式代碼段裡。總結起來就是,庫檔案通過頭檔案向外導出接口。使用者通過頭檔案找到庫檔案中函數實作的代碼進而把這段代碼連結到使用者程式中去。