【问题标题】:How do you include a header file that may or may not exist?如何包含可能存在或不存在的头文件?
【发布时间】:2012-07-19 03:47:49
【问题描述】:

假设我在 foo.h 中定义了 BAR。但是 foo.h 可能不存在。我如何包含它,而不会让编译器抱怨我?

#include "foo.h"

#ifndef BAR
#define BAR 1
#endif

int main()
{
    return BAR;
}

因此,如果 BAR 在 foo.h 中定义为 2,那么如果 foo.h 存在则程序将返回 2,如果 foo.h 不存在则返回 1。

【问题讨论】:

标签: c gcc include header-files


【解决方案1】:

一般来说,你需要做一些外部的事情来做到这一点 - 例如。通过使用搜索路径(如 cmets 中的建议)并提供一个空的 foo.h 作为后备,或者将 #include 包装在 #ifdef HAS_FOO_H...#endif 中并设置 HAS_FOO_H通过编译器开关(-DHAS_FOO_H 用于 gcc/clang 等)。

如果您知道自己正在使用特定的编译器,并且可移植性不是问题,请注意,某些编译器确实支持将可能存在或不存在的文件作为扩展名包含在内。例如,参见 clang 的 __has_include 功能。

【讨论】:

  • 第二个 foo.h 后备文件是最简单的解决方案。
  • 这也是一个糟糕的解决方案,因为如果真正的 foo.h 更改其内部标头保护 #define,您会受到细微的破坏。
  • 为什么?后备的 foo.h 是空的。
  • 我猜 Jack 将 HAS_FOO_H 误读为在真正的 foo.h 中定义的东西。但杰克有一个观点。后备 foo.h 不应为空。它应该定义一个符号,表明使用了回退。这比依赖真正的 foo.h 中的任何符号要好。 API 可以更改,宏可以更改为 C 常量。
【解决方案2】:

使用像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 开始。

【讨论】:

  • Autotools 可能……嗯,很痛苦,而且现在完全没有必要了。 Mac 和 Linux 具有出色的 CMake 支持,还有其他不错的构建系统(例如 SCons)。 ESR 有一个特别尖锐的帖子值得考虑:Autotools must die
  • CMake 带来的痛苦远远超过了 autotools。 news.ycombinator.com/item?id=2357014 。它将受 MSVC 启发的构建类型模型强制引入 unix 领域,附带一种新的笨拙的编程语言,该语言缺少适当的数据结构,并以 ad-hoc 方式扩展,内置随机事物(qt4!?fltk!?)。 ESR 的咆哮全是尖酸刻薄,没有实质内容。我在多个项目中使用过 CMake、SCons 和 autotools,几乎每次都会使用 autotools。要替换 autotools,您无需编译为 makefile。 make 的模型被巧妙地破坏了,替换者必须明白这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-13
  • 2014-12-15
  • 2017-10-02
  • 1970-01-01
  • 2011-01-20
相关资源
最近更新 更多