今天在查看glibc-2.20源码以了解线程私有数据机制是如何实现时,偶然跟踪到#include_next <pthread.h>,因之前并未接触到#include_next,故对你使用很是疑惑。
google到http://lists2.linuxjournal.com/pipermail/linux-list/2000-August/006073.html处给出了what's include_next的解释,大致翻译如下:
继承是发生在通过拷贝其它对象或文件的内容从而衍生出一个新的对象或文件的一种机制。对于C语言的头文件来说,继承就是一个头文件包含另一个头文件,然后替换或增加一些内容。
如果衍生头文件和基础头文件(base header file)的文件名不同,继承是显而易见的,只需简单的在衍生头文件中加上“#include<base>”即可。
但是,有时候我们需要使衍生出来的头文件和基础头文件的文件名相同。如假设一个应用程序需要使用系统头文件sys/signal.h,但是在某些系统上/usr/include/sys/signal.h不完全和应用程序期望的一样,那么定义一个本地("local" version)的头文件将会很方便,如定义/usr/local/include/sys/signal.h来覆盖或补充系统提供的头文件。
首先写出满足程序期望的头文件/usr/local/include/sys/signal.h,然后在编译时增加"-I /usr/local/include"选项。但是如果要在新的头文件中包含标准的sys/signal.h,通过在新的文件中增加"#include <sys/signal>"是不可能实现的。因为这样包含的是文件本身而不是系统的头文件,从而导致无限的递归及编译错误。
在新的头文件中增加"#include </usr/include/sys/signal.h>"固然可以解决,但是这种方式的缺点是固定了系统头文件的位置,如果系统头文件的位置改变了,这种方法就会失效。另一种简单的方法是使用"#include_next",表示包含文件名为该名字的下一个头文件。
假如,我们编译时指定了“-I /usr/local/include/”,而且搜索目录列表中包含“/usr/include”,两个目录中都包含“sys/signal.h”文件。那么,当使用“include<sys/signal.h>”时,编译器将使用在"/usr/local/include"的文件,而当使用“include_next<sys/signal.h>”时,编译器在“/usr/local/include”目录外开始搜索以找到“/usr/include”中的“sys/signal.h”文件。
总结起来,即预处理指令#include_next是#include的一个变体,其只在包含当前源文件(即使用#include_next的文件)的目录后开始根据搜索路径列表搜索头文件,这样就使得将一个标准头文件扩充以满足特定应用需求时,可以在扩充成的同名新文件中引用标准头文件了。
下面的例子很好的示范了#include_next的使用,例子中path2和path1中都包含t.h,假设path1和path2都在搜索目录列表中,#include_next"t.h" 将跳过path1,最终在path2中找到t.h文件。
/* t.c */
#include "t.h"
int main()
{
printf("%d", ret_val);
}
/* t.h in path1 */
#include_next "t.h"
int ret_val = RET;
/* t.h in path2 */
#define RET 55;