#include的用法

在C/C++中, #include是preprocessor的一条指令, 负责把 #include 的文件中的内容全部copy到当前文件的#include所在的位置,也就是用该文件中的内容取代#include 这条指令。

 

因为#include是preprocessor自身的行为,因此怎么对该指令解释,也是preprocessor已经定义好的。 所以不同的preprocessor就可能有不同的操作方法,即implementation-defined

 

#include 头文件时有两种方法: #include "xxx.h" 和 #include<xxx.h>, 由于 #include的行为是preprocessor定义的,因此这两种形式的具体行为,就是preprocessor指定好的。 既然二者都是copy其他文件中的内容,那么区别在哪里?

 

区别在于搜索header文件时,二者的搜索路径!! 仅此而已。

 

通常#include后面只跟了一个header文件的basename或者一个relative path, 而非absolute path,如果都是absolutename,那也就无所谓搜索路径了, 但是这样的可移植性=0,没法使用。

因此preprocessor在解释#include命令的时候需要知道从哪些路径中查找这些header文件。

 

搜索路径也只有下面3个:

1. 当前source文件所在的目录,即当前目录

2. 通过一些编译器参数添加的路径,如gcc -I include_dir; gcc -iquote include_dir,或者Cmake的include_directories()

3. 标准系统include路径, 这个其实是编译器自己定义的一些默认路径,比如标准库所在的path。

 

也就是说,preprocessor会保存这些搜索路径,在预处理时使用。 并且给这些路径排了序。使用时严格按照顺序搜索, 如果在前面出现的路径中搜索到了要include的文件,那么就不会在后面的路径中搜索了。

搜索路径的次序:

  1. 当前目录
  2. gcc -iquote 设置的include_dir,可以多次使用gcc -iquote 设置多个路径,这些路径的搜索次序和gcc命令使用的次序一致。
  3. gcc -I 设置的include_dir中,可以多次使用gcc -I 设置多个路径,这些路径的搜索次序和gcc命令使用的次序一致。
  4. 标准系统include 路径。 gcc的标准include路径可以通过cpp -v 或者

For C: gcc -xc -E -v -

For C++: gcc -xc++ -E -v -

得到。 其中列出的标准路径的次序也是严格执行的。而且试图通过gcc -I或者gcc-iquote将这些路径调整到前面的行为也是徒劳的。 因为gcc会判断这个出现的次序,并且ignore你的操作。 它认为某路径A和路径B的次序只能这样,而如果B出现在A前面,认为B是duplicate,然后ignore掉。

 

#include<> 和 #include"" 实际操作的区别,也就是在于对这些搜索路径的使用上。

#include "xxx.h" 的搜索方式:

  1. 在当前目录查找
  2. 在用gcc -iquote 设置的include_dir中查找,可以多次使用gcc -iquote 设置多个路径,这些路径的搜索次序和gcc命令使用的次序一致。
  3. 在用gcc -I 设置的include_dir中查找,可以多次使用gcc -I 设置多个路径,这些路径的搜索次序和gcc命令使用的次序一致。
  4. 在标准系统include 路径查找。

 

#include <xxx.h> 的搜索方式:

  1. 在用gcc -I 设置的include_dir中查找,可以多次使用gcc -I 设置多个路径,这些路径的搜索次序和gcc命令使用的次序一致。
  2. 在标准系统include 路径查找。

这些都可以在用cpp -v 指令看到,例如

cpp -iquote hdr1 -I hdr2 -v ... #include "..." search starts here: (从此开始,一直到/usr/include) hdr1 #include <...> search starts here:(从此开始,一直到/usr/include, 不会搜索上面的路径)

hdr2 /usr/local/include /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include-fixed /usr/include/x86_64-linux-gnu /usr/include

 

可以看到, #include “xxx.h"的行为,全面cover了#include<>,所以在使用的时候,一定要清楚#include<>在哪里start的,否则会出现无法找到xxx.h的问题。  

 

Questions:

1. 既然#include“xxx.h” cover了 #include<xxx.h>,为何还需要后者?

A: 如果确定header文件在标准include路径,那么之间使用#include<>的效率更高。

2. #include<xxx.h> 会不会在gcc -I 的directory和标准include path中搜不到header文件后,再去当前目录搜索?

A: 不会,因为#include<xxx.h>的搜索路径是已经定义好的。

3. 使用cmake的include_directories() 包含的include 路径的次序在标准include之前吗?

A: 是的,如上分析所述。

 

Reference:

https://gcc.gnu.org/onlinedocs/gcc-4.8.0/cpp/Search-Path.html

https://commandlinefanatic.com/cgi-bin/showarticle.cgi?article=art026

  • 14
    点赞
  • 78
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值