2010-06-11 72 views
3

test.c哪些目錄在C/C++中包含語句搜索?

#include "file.h" 

在上面的語句,目錄將被搜索?

我想test.c所在的目錄將被搜索,對不對?

但是,所有?

順便說一句,使用頭文件有什麼好處? Java不需要頭文件...

+0

哪個編譯器/平臺? – Stephen 2010-06-11 16:27:11

回答

2

它由您的編譯器控制。例如,gcc有一個-I選項來指定包含路徑。

C和C++原型是必需的,所以編譯器(區別於鏈接器)可以確保函數被正確的參數調用。 Java不同之處在於,編譯器使用二進制.class文件(與C不同,它以標準字節碼格式保存所有類型信息)來檢查調用是否有效。

+0

但是應該有一些默認的搜索路徑,比如'stdlib.h'所在的位置,對吧? – user198729 2010-06-11 16:12:00

+1

您的問題詢問''test.h「',而不是''。像stdlib.h這樣的標準頭文件使用括號語法(''),並且這些頭文件位於默認系統路徑中。 – 2010-06-11 16:13:38

7
  • #include <header_name>:標準包含文件:看在標準路徑(系統包括編譯器的路徑設置)第一
  • #include "header_name":看看在當前路徑,然後再在包含路徑(項目特定查找路徑)

使用頭文件的好處是爲其他人提供庫的接口,而無需實現。 Java並不要求它,因爲Java字節碼或jar能夠描述自己(反射)。 C代碼不能(但)做到這一點。

在Java中,您只需要jar並擁有正確的使用語句。在C中,你將(主要)需要一個頭文件和一個lib文件(或者頭文件和dll文件)。

另一個原因是c代碼編譯的方式。編譯器編譯翻譯單元(一個包含所有頭文件的c/cpp文件),鏈接器在第二步中鏈接整個東西。聲明不能被編譯,這樣可以節省時間,並避免代碼被鏈接器清理的每個編譯單元無用地生成。

這只是一個普遍的想法,我不是一個編譯器專家,但應該有所幫助。

+0

什麼是標準路徑,爲什麼C/C++中不可能使用反射? – user198729 2010-06-11 16:13:01

+0

存在系統頭文件的系統(可能依賴於編譯器)路徑。例如,* nix系統傾向於使用'/ usr/include /'等 – Dusty 2010-06-11 16:15:37

+0

標準包含路徑是系統特定的,並且在C++中根本不需要使用文件系統。編譯器無法使用編譯的庫檢查類型的原因是該類型信息並未全部保留,並且沒有標準的ABI(應用程序二進制接口)。 – 2010-06-11 16:17:58

0

#include之後使用引號指示預處理器在包含#include語句的文件的同一目錄中查找包含文件,然後在包含(#include)該文件的任何文件的目錄中查找包含文件。預處理器然後沿着由/ I編譯器選項指定的路徑搜索,然後沿着由INCLUDE環境變量指定的路徑搜索。

如果使用尖括號形式,它將指示預處理器首先沿着/ I編譯器選項指定的路徑搜索包含文件,然後在從命令行進行編譯時沿着由INCLUDE環境指定的路徑變量。

+0

需要注意的是,當使用尖括號時,除非當前目錄位於路徑中,否則編譯器不*查看當前目錄。因此,如果'#include '''#include '(注意沒有路徑),並且bh與ah在同一個目錄中,'#include '將會失敗if該目錄不在路徑中。 – 2010-06-11 18:01:00

+0

正是由於這個原因,我經常咆哮人們應該幾乎從不在他們自己的代碼中使用#include語句中的尖括號,但是這種咆哮通常是充耳不聞。 – 2010-06-11 18:02:06

0

strace桁架等可能有幫助。例如,使用單行#include "foo.h"創建一個文件foo.c。然後在Cygwin的命令:

strace /usr/bin/gcc-4.exe foo.c | grep 'src_path.*foo.h,' | sed 's/.*src_path //;s/foo.h.*//' 

生產:

foo.c:1:22: error: foo.h: No such file or directory 

/home/Joe/src/utilities/ 
/usr/lib/gcc/i686-pc-cygwin/4.3.4/include/ 
/usr/lib/gcc/i686-pc-cygwin/4.3.4/include-fixed/ 
/usr/include/ 
/usr/include/w32api/ 

實際上,我是驚訝這個名單是如此之短:上一次我十五年前做這個測試,在SunOS 4,搜索路徑有十幾個目錄。

顯然,第一個目錄是foo.c存在的地方。環境變量CPATHC_INCLUDE_PATH的環境變量見http://gcc.gnu.org/onlinedocs/cpp/Environment-Variables.html。但是這些沒有在我的機器上設置。 (而且我不清楚是否CYGWIN使用它們,反正。)

編輯:最簡單的解決方法是使用cpp -vGCC -v)。它給出:

COLLECT_GCC_OPTIONS='-E' '-v' '-mtune=generic' '-march=i686' 
/usr/lib/gcc/i686-pc-cygwin/4.3.4/cc1.exe -E -quiet -v -D__CYGWIN32__ -D__CYGWIN__ 
     -Dunix -D__unix__ -D__unix -idirafter /usr/lib/gcc/i686-pc-cygwin/4.3.4/../../../.. 
     /include/w32api -idirafter 
     /usr/lib/gcc/i686-pc-cygwin/4.3.4/../../../../i686-pc-cygwin/lib/../../include/w32api - 
     -mtune=generic -march=i686 
ignoring nonexistent directory "/usr/local/include" 
ignoring nonexistent directory "/usr/lib/gcc/i686-pc-cygwin/4.3.4/../../../../i686-pc-cygwin/include" 
ignoring duplicate directory "/usr/lib/gcc/i686-pc-cygwin/4.3.4/../../../../i686-pc-cygwin/lib/../../include/w32api" 
#include "..." search starts here: 
#include <...> search starts here: 
/usr/lib/gcc/i686-pc-cygwin/4.3.4/include 
/usr/lib/gcc/i686-pc-cygwin/4.3.4/include-fixed 
/usr/include 
/usr/lib/gcc/i686-pc-cygwin/4.3.4/../../../../include/w32api 
End of search list. 
+0

編輯:和更多的gcc文檔:http://gcc.gnu.org/onlinedocs/cpp/Search-Path.html#Search-Path – 2010-06-11 21:07:55

0

C++標準並沒有說明應該搜索哪些目錄。這是C++標準是如何描述時#include "somefile.h"遇到什麼情況:

形式

# include "q-char-sequence" new-line 

的預處理指令由源文件中標識的 的全部內容導致的替代品。 指令由 指定的序列之間的「 」分隔符。指定的源文件是 搜索 執行定義的方式。如果這個 搜索不是支撐,或者如果 搜索失敗,該指令是 再處理,就好像它與含有相同序列 讀

# include <h-char-sequence> new-line 

(包括>字符,如果有的話)從 原始指令。

那麼究竟是哪些目錄被搜索是在你的具體C++實現的擺佈。

+0

@ Neil:在我的機器上,'-print-search-dirs'不包括任何包含目錄。 – 2010-06-11 19:29:45

+0

@Joseph B * gger。你是對的 - 我可以發誓這樣做,但它只打印可執行文件和庫搜索路徑。 – 2010-06-11 19:35:49