2012-07-19 76 views
6

我們假設我在foo.h中定義了BAR。但是foo.h可能不存在。如果沒有編譯器抱怨我,我該如何包含它?如何包含可能存在或不存在的頭文件?

#include "foo.h" 

#ifndef BAR 
#define BAR 1 
#endif 

int main() 
{ 
    return BAR; 
} 

因此,如果BAR定義爲foo.h中爲2,則程序將如果存在foo.h中和1如果foo.h中不存在返回2。

+0

提供您自己的fallback foo.h來定義'BAR',並相應地配置編譯器的搜索路徑? – 2012-07-19 21:34:00

+0

我想我可以做到這一點。爲什麼fallback foo.h需要包含任何內容? – theanine 2012-07-19 21:35:50

+0

[可以使用C預處理器來判斷文件是否存在?](http://stackoverflow.com/questions/142877/can-the-c-preprocessor-be-used-to-tell-if- a-file-exists) – 2015-08-02 08:36:03

回答

8

一般而言,您需要做一些外部操作 - 例如通過做一些像玩弄搜索路徑(如評論中所建議的)並提供空的foo.h作爲回退,或將#include封裝在#ifdef HAS_FOO_H ... #endif內並且通過編譯器開關設置HAS_FOO_H(用於gcc/clang的-DHAS_FOO_H等等。)。

如果您知道您正在使用特定的編譯器,並且可移植性不是問題,請注意某些編譯器支持將包含可能存在或可能不存在的文件作爲擴展。例如,請參閱clang的__has_include功能。

+0

第二個foo.h後備文件是最簡單的解決方案。 – theanine 2012-07-20 16:51:15

+1

這也是一個不好的解決方案,因爲如果真正的'foo.h'改變了它的內部頭文件'guard',你會得到微妙的破壞。 – 2012-07-22 07:07:47

+1

爲什麼?回退foo.h是空的。 – theanine 2012-07-24 17:32:02

6

使用像GNU Autoconf這樣的工具,這就是它的設計目的。 (在windows上,您可能更喜歡使用CMake)。

因此,在你configure.ac,你就會有這樣一行:

AC_CHECK_HEADERS([foo.h]) 

其中,運行configure後,將定義HAVE_FOO_H,你可以測試這樣的:

#ifdef HAVE_FOO_H 
#include "foo.h" 
#else 
#define BAR 1 
#endif 

如果您打算去autotools路由(即autoconf和automake,因爲他們一起工作很好),我建議你從這個excellent tutorial開始。

+0

Autotools可以...好,痛苦,而且這些日子完全沒有必要。 Mac和Linux具有出色的CMake支持,還有其他很好的構建系統(如[SCons](http://www.scons.org/))。 ESR有一個值得考慮的特別重要的職位:[Autotools必須死亡](http://esr.ibiblio.org/?p=1877)。 – sfstewman 2012-07-25 01:14:13

+4

CMake造成的痛苦遠遠超過了autotools'。 http://news.ycombinator.com/item?id=2357014。它迫使一個MSVC模式的構建類型到unix的土地上,帶來了一種新的笨拙的編程語言,它缺少適當的數據結構,並以隨機的內置方式(qt4 !? fltk !?)以特別的方式擴展。 ESR的咆哮都是硫酸,沒有任何物質。我已經在幾個項目中使用過CMake,SCons和autotools,幾乎每次都會去autotools。要取代autotools,你不需要編譯makefile。 'make'的模型被巧妙地打破了,替代者必須明白這一點。 – 2012-07-25 05:32:06