本文介紹在linux中頭文件的搜索路徑,也就是說你通過include指定的頭文件,linux下的gcc編譯器它是怎麼找到它的呢。在此之前,先了解一個基本概念。
頭文件是一種文本文件,使用文本編輯器將代碼編寫好之後,以擴展名.h保存就行了。頭文件中一般放一些重復使用的代碼,例如函數聲明、變量聲明、常數定義、宏的定義等等。當使用#include語句將頭文件引用時,相當於將頭文件中所有內容,復制到#include處。#include有兩種寫法形式,分別是:
#include <> : 直接到系統指定的某些目錄中去找某些頭文件。
#include “” : 先到源文件所在文件夾去找,然後再到系統指定的某些目錄中去找某些頭文件。
#include文件可能會帶來一個問題就是重復應用,如a.h引用的一個函數是某種實現,而b.h引用的這個函數卻是另外一種實現,這樣在編譯的時候將會出現錯誤。所以,為了避免因為重復引用而導致的編譯錯誤,頭文件常具有:
#ifndef LABEL
#define LABEL
//代碼部分
#endif
的格式。其中LABEL為一個唯一的標號,命名規則跟變量的命名規則一樣。常根據它所在的頭文件名來命名,例如,如果頭文件的文件名叫做hardware.h,那麼可以這樣使用:
#ifndef __HARDWARE_H__
#define __HARDWARE_H__
//代碼部分
#endif
這樣寫的意思就是,如果沒有定義__HARDWARE_H__,則定義__HARDWARE_H__,並編譯下面的代碼部分,直到遇到#endif。這樣當重復引用時,由於__HARDWARE_H__已經被定義,則下面的代碼部分就不會被編譯了,這樣就避免了重復定義。
一句話,頭文件事實上只是把一些常用的命令集成在裡面,你要用到哪方面的命令就載入哪個頭文件就可以了。
gcc尋找頭文件的路徑(按照1->2->3的順序)
1. 在gcc編譯源文件的時候,通過參數-I指定頭文件的搜索路徑,如果指定路徑有多個路徑時,則按照指定路徑的順序搜索頭文件。命令形式如:“gcc -I /path/where/theheadfile/in sourcefile.c“,這裡源文件的路徑可以是絕對路徑,也可以是相對路徑。eg:
設當前路徑為/root/test,include_test.c如果要包含頭文件“include/include_test.h“,有兩種方法:
1) include_test.c中#include “include/include_test.h”或者#include "/root/test/include/include_test.h",然後gcc include_test.c即可
2) include_test.c中#include <include_test.h>或者#include <include_test.h>,然後gcc –I include include_test.c也可
2. 通過查找gcc的環境變量C_INCLUDE_PATH/CPLUS_INCLUDE_PATH/OBJC_INCLUDE_PATH來搜索頭文件位置。
3. 再找內定目錄搜索,分別是
/usr/include
/usr/local/include
/usr/lib/gcc-lib/i386-linux/2.95.2/include
最後一行是gcc程序的庫文件地址,各個用戶的系統上可能不一樣。
gcc在默認情況下,都會指定到/usr/include文件夾尋找頭文件。
gcc還有一個參數:-nostdinc,它使編譯器不再系統缺省的頭文件目錄裡面找頭文件,一般和-I聯合使用,明確限定頭文件的位置。在編譯驅動模塊時,由於非凡的需求必須強制GCC不搜索系統默認路徑,也就是不搜索/usr/include要用參數-nostdinc,還要自己用-I參數來指定內核頭文件路徑,這個時候必須在Makefile中指定。
4. 當#include使用相對路徑的時候,gcc最終會根據上面這些路徑,來最終構建出頭文件的位置。如#include <sys/types.h>就是包含文件/usr/include/sys/types.h