标签:
A: #include "..." 和 #include <...> 有什么区别?
B: 他喵的, 这么简单的问题. 尖括号是先在系统目录下找, 双引号是首先在当前目录下找, 找不到就找系统目录.
A: 说得很含糊. 那么我问你, 当前目录有个叫hdr.h的文件,
当前目录下还有一个子目录sub, sub里面有两个文件hdr.h和1.c,
1.c中#include "hdr.h",
那么在当前目录编译sub/1.c, 它应该包含哪一个hdr.h?
bash-3.2$ tree |-- sub | |-- 1.c | `-- hdr.h `-- hdr.h bash-3.2$ cat sub/1.c #include "hdr.h" bash-3.2$ gcc -c sub/1.c
B: 应该包含外面的hdr.h吧, 因为它在gcc工作的当前目录, 而子目录的hdr.h不在当前目录, 应该搜不到.
A: 错, 包含的是sub/hdr.h !
B: 啊!... 喔... 双引号是首先在使用include的源文件所在目录找(也就是1.c所在的目录sub找), 而不是编译器当前工作目录找, 我原来理解错了.
A: 是的, gcc和msvc的include双引号都是先在使用include的源文件所在目录找.
B: C99标准是怎么规定的? 是源文件当前目录还是编译器工作目录?
A: 其实C99标准没有规定#include "..." 先找哪个目录, 只说取决于实现, 你可以设计一个C编译器include双引号时按你设计的方式找(如果找不到退化为#include <...>). 但事实上的工业标准是"双引号优先从使用include的源文件所在目录".
B: 明白了.
A: 那么我再问你, #include <...> 所谓的"从系统目录找", 那么"系统目录"到底有哪些, 怎么看呢?
B: 编译时-I指定的目录呗.
A: 如果没指定-I的参数时, 是不是系统目录列表就是空的?
B: 当然不是, 有默认的吧.
A: 怎么看默认的?
B: 这个不知道. 怎么看?
A: 以gcc为例, 在命令行运行 echo | gcc -E -v -
bash-3.2$ echo | gcc -E -v - * * * #include "..." search starts here: #include <...> search starts here: /usr/lib/gcc/i686-pc-linux-gnu/4.8.2/include /usr/local/include /usr/lib/gcc/i686-pc-linux-gnu/4.8.2/include-fixed /usr/include End of search list.
B: 那么我指定gcc -I. 时是把 . 作为搜索路径还是把当前目录转成绝对路径加入到列表中呢?
A: 这个问题问得好! 其实我也不知道, 要不我们试一下.
bash-3.2$ echo | gcc -E -v -I. - * * * #include "..." search starts here: #include <...> search starts here: . /usr/lib/gcc/i686-pc-linux-gnu/4.8.2/include /usr/local/include /usr/lib/gcc/i686-pc-linux-gnu/4.8.2/include-fixed /usr/include End of search list.
B: 并没有转成绝对路径, 就是一个点.
A: 恩, 那么问题来了, 下面这种情形下( 注意: 1.c的内容修改为 #include <hdr.h> ), 会包含那个hdr.h ?
bash-3.2$ tree |-- sub | |-- 1.c | `-- hdr.h `-- hdr.h bash-3.2$ cat sub/1.c #include <hdr.h> bash-3.2$ gcc -c -I. sub/1.c
B: 我猜会用子目录的hdr.h.
A: 我猜会用外层的hdr.h,
在hdr.h写个1,
在sub/hdr.h写个2,
然后 gcc -E -I. sub/1.c.
你看结果是1, 我猜对了!
B: 嗯, 看来搜索路径列表是基于编译器工作路径的.
标签:
原文地址:http://my.oschina.net/2bit/blog/389556