? ? ? ? 首先說明庫文件與頭文件在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這個函數的實現并鏈接進這個程序代碼段里。總結起來就是,庫文件通過頭文件向外導出接口。用戶通過頭文件找到庫文件中函數實現的代碼從而把這段代碼鏈接到用戶程序中去。