標籤:style color 使用 os io 檔案 ar cti
在Linux下開發c程式時,經常引用各類庫,通常通過包含多個#include<xxx.h>來完成庫的引用,對背後的一些機制沒有完全理解。本文重點說明c程式開發中的庫檔案引用、動態連結程式庫和靜態連結庫中的一些常見疑問。不特別指明時,編譯器指定GCC。
在學習c語言預先處理過程時,我們瞭解到#include <xxx.h>和#include “xxx.h”的差別,前者在指定目錄中尋找標頭檔,後者則在源檔案所在目錄中尋找標頭檔,如果沒有找到,再到指定目錄中繼續尋找。通常我們在引用標頭檔時最好區別使用””和<>,這樣可以加速預先處理效率。
在Linux系統中,指定目錄通常是/usr/include目錄,因此我們在來源程式中使用#include <stdio.h>,編譯器實際會去尋找/usr/include/stdio.h檔案。實際項目開發中,如果我們有多個標頭檔,通常都將標頭檔集中在單獨的目錄中,對於這類情況我們不喜歡每次#include都要包括一長串的路徑,這時候我們可以在編譯命令中加入-I命令來指定標頭檔目錄,命令格式是:
gcc –I 標頭檔檔案夾(絕對、相對路徑均可) 源檔案(可以是多個)
我們首先說明一下GCC搜尋標頭檔順序,在以一個小例子來說明如何指定自己的標頭檔目錄。
GCC在預先處理階段,搜尋標頭檔順序是:
a、 由-I指定的路徑開始搜尋,-I指定多個路徑時順序搜尋。
b、 gcc環境變數指定的路徑:C_INCLUDE_PATH、CPLUS_INCLUDE_PATH、OBJC_INCLUDE_PATH。
c、 內定目錄:/usr/include/,/usr/local/include/,/usr/lib/gcc-lib/i386-linux/xxx/include/等。
注意:編譯時間指定-nostdinc選項後,GCC不會到預設目錄中尋找標頭檔,僅在-I指定的目錄中尋找。
我們以一個小例子來說明如何使用-I選項指定自訂標頭檔目錄:
有如下幾個源檔案main.c,stdio.c include/stdio.h
main.c代碼如下:
1: #include <stdio.h>
2:
3: int main(int argc, char *argv[])
4: {
5:
6: return myfunc();
7: }
stdio.c代碼如下:
1: int myfunc(void)
2: {
3:
4: return 10;
5: }
include檔案夾下stdio.h代碼如下:
1: #ifndef _STD_IO_H_
2: #define _STD_IO_H_
3:
4: int myfunc(void);
5:
6: #endif
首先,我們直接編譯產生main,不加其它選項,結果如下:
1: $:gcc -o main main.c
2: /tmp/cchbeKLd.o: In function `main‘:
3: main.c:(.text+0x7): undefined reference to `myfunc‘
4: collect2: ld returned 1 exit status
因為標準庫stdio.h中沒有myfunc(void)函數,因此編譯肯定失敗。
然後,我們引用自己的庫檔案,結果如下:
1: ##不引用標準庫,設定include為庫尋找目錄
2: $:gcc -nostdinc -I include -o main stdio.c main.c
3: $:./main ##執行沒有任何輸出
4: $:echo $? ##列印main函數返回值
5: $:10 ##查看main.c檔案,返回值為10,驗證正確
從執行結果中看到順利調用了myfunc()函數。
在實際項目中,可以在makefile中添加自己的引用目錄,也可以在環境變數C_INCLUDE_PATH中添加自己的目錄。如果將自己的標頭檔目錄添加到C_INCLUDE_PATH中,那麼你需要將你的程式編譯為靜態庫或動態庫,添加到特定目錄中。這涉及到動態庫、靜態庫的內容,我將在另一篇文章中說明。
希望讀完這篇文章後,希望能對你布局自己的標頭檔有所協助,如有錯誤請批評指正,謝謝!