为啥要在项目中使用#include_next?
Posted
技术标签:
【中文标题】为啥要在项目中使用#include_next?【英文标题】:Why would one use #include_next in a project?为什么要在项目中使用#include_next? 【发布时间】:2012-05-02 22:24:16 【问题描述】:引用iosDocumentation on Wrapper Headers:
#include_next
不区分和 "file" 包含,也不检查您指定的文件是否具有相同的 名称为当前文件。它只是查找名为的文件,开始 搜索路径中的目录位于当前目录之后 文件已找到。 使用 `#include_next' 会导致很大的混乱。我们推荐 只有在没有其他选择时才使用它。特别是,它 不应在属于特定程序的标头中使用;它 应该只用于沿线进行全局更正 修复包括。
那么,两个问题,#include_next 是什么,你为什么需要使用它?
【问题讨论】:
ffmpeg 库中的一个例子:#ifndef FFMPEG_COMPAT_AIX_MATH_H #define FFMPEG_COMPAT_AIX_MATH_H #define class class_in_math_h_causes_problems #include_next <math.h> #undef class #endif /* FFMPEG_COMPAT_AIX_MATH_H */
【参考方案1】:
如果您想用您自己的制作替换默认标题,则使用它,例如,假设您想替换“stdlib.h”。您将在项目中创建一个名为 stdlib.h 的文件,该文件将被包含在内,而不是默认标头。
#include_next 用于向 stdlib.h 添加一些东西而不是完全替换它。您创建一个名为 stdlib.h 的新文件,其中包含:
#include_next "stdlib.h"
int mystdlibfunc();
并且编译器不会再次递归地包含你的 stdlib.h,就像普通的#include 一样,而是继续在其他目录中查找名为“stdlib.h”的文件。
【讨论】:
【参考方案2】:如果您支持某个东西的多个版本,它会很方便。例如,我正在编写支持 PostgreSQL 9.4 和 9.6 的代码。存在许多内部 API 更改,主要是现有函数的新参数。
兼容性标头和包装函数
我可以使用 static inline
包装函数编写兼容性标头,并为所有内容使用新名称,基本上是包装 API,我在代码中的任何地方都使用包装名称。说something_compat.h
:
#include "something.h"
static inline something*
get_something_compat(int thingid, bool missing_ok)
assert(!missing_ok);
return get_something(thingid);
但是将_compat
或任何后缀分散在任何地方都很难看。
包装头
相反,我可以在针对旧版本构建时在包含路径中插入一个兼容性标头,例如compat94/something.h
:
#include_next "something.h"
#define get_something(thingid, missing_ok) \
( \
assert(!missing_ok), \
get_something(thingid) \
)
所以其余的代码可以只使用 9.6 签名。在针对 9.4 构建时,我们会将 -Icompat94
前缀到标题搜索路径。
需要注意防止多次评估,但如果您使用#include_next
,您显然不介意依赖 gcc。在这种情况下,您也可以使用statement expressions。
当新版本是“主要”目标时,这种方法很方便,但在有限的时间段内需要旧版本的向后兼容性。因此,您将逐步弃用旧版本,并尝试参考当前版本保持代码整洁。
替代方案
或者做个懂事的人,用C++,用重载函数和模板内联函数:p
【讨论】:
【参考方案3】:include_next 用作预处理器指令,告诉编译器从解析到此头文件中排除直到并包括文件名 file.h 的搜索路径。典型的需要是当需要使用两个同名的头文件时。谨慎使用此类功能,仅在绝对必要时使用。
例如:
源 file.c 内容与路径 1 中的通常 file.h:#include <file.h>
int main()
printf("out value: %d", out_val);
exit 0;
路径 1 中的 file.h 头文件包含路径 2 中的 file.h 内容:
include_next 指示路径 1 子目录不用作 file.h 的搜索路径,而是使用路径 2 子目录作为搜索路径。这样,您可以拥有 2 个同名文件,而不必担心调用对自身的循环引用。
# include_next <file.h>
int out_val = UINT_MAX - INT_MAX;
路径 2 内容中的 file.h
#define INT_MAX 1<<63 - 1
#define UINT_MAX 1<<64 - 1
【讨论】:
以上是关于为啥要在项目中使用#include_next?的主要内容,如果未能解决你的问题,请参考以下文章
eclipse 一个项目中 要建4个包,为啥建的包不是在同一目录(src)下。。而是要在Libraries下。。
为啥要在 didFinishLaunchingWithOptions 中使用 UIApplicationLaunchOptionsRemoteNotificationKey?