这两天被问到一个很有意思的问题:C头文件中尖括号与双引号有什么区别,以前只大约知道 <> 常用在系统库文件,"" 常用在自定义的借口文件中,那具体在gcc编译搜索过程中有啥区别,还得仔细查阅一番相关文档。

针对 <>  与 "" 的区别有如下解释:

摘抄自:https://gcc.gnu.org/onlinedocs/cpp/Include-Syntax.html#Include-Syntax

而在搜索时的区别,则做如下优先级排序:

摘抄自: https://gcc.gnu.org/onlinedocs/gcc/Directory-Options.html#Directory-Options

简单理解就是:

1. 尖括号告诉编译器去搜索标准系统目录,可使用 -I 选项添加其它搜索目录

2. 双引号告诉编译器先搜索以源文件路径为参考的目录,其次搜索引号目录,最后搜索标准系统目录, -iquote 选项可添加其它目录到引号目录列表中。

源文件路径为参考的目录

如何理解其含义呢,以实际情况为例,本地存在一个header/目录,其内部目录树结构如下所示:

图中的hello.c文件,是这样包含头文件的:#include "..inc/hello.h"

测试1. shell 处在 ~/header/src/ 目录,跟踪gcc 的编译搜索过程: strace -f -o log gcc say_hello.c ,查看log输出:

从图中的搜索路径可知:因源文件刚好处在gcc执行目录下,因此在编译时,源文件的相对执行目录为 . , dot默认可省略,再拼接上#include "../inc/hello.h" 引号内的路径,那么gcc会定位到 "../inc/say_hello.h" 去搜索hello.h文件

测试2. shell处在 ~/header/ 目录,跟踪gcc的编译搜索过程:strace -f -o log gcc ../src/say_hello.c,查看log输出:

从图中搜索路径可知:因源文件在gcc目录的下一级目录,因此在编译时,源文件的相对执行目录为  src/ , 再拼接上 #include "../inc/hello.h" 引号内的路径,那么gcc会定位到 "src/../inc/say_hello.h" 去搜索hello.h文件.

所以从测试结果来看,gcc编译时,以执行目录为参考点来定位源文件的路径,再以源文件为参考点来定位头文件路径。在上述测试中,~/header/src/say_hello.h 文件始终是被忽略的,除非代码中写成 #include "say_hello.h" 。

C头文件中尖括号与双引号的区别及编译搜索顺序的更多相关文章

  1. C++包含头文件时尖括号和双引号区别

    原文链接:http://c.biancheng.net/cpp/biancheng/view/66.html 如果你还看一些别的C++教程,那么你可能很早就发现了,有些书上的#include命令写作# ...

  2. 转载 关于include尖括号和双引号的区别。

    对于使用尖括号( < >),预处理程序cpp在系统预设包含文件目录(如/usr/include)中搜寻相应的文件,而对于使用双引号(“ ”),cpp在当前目录中搜寻头文件,这个选项的作用是 ...

  3. C++中#include <xxx.h>和#include "xxx.h"的区别(尖括号和双引号的区别)

    第一种方式:采用< >方式,表示让编译器在编译器的预设标准路径下去搜索相应的头文件,如果找不到则报错. 例如:VS2015的安装目录\Microsoft Visual Studio 14. ...

  4. C++ #include—尖括号和双引号的区别

    如果你还看一些别的C++教程,那么你可能很早就发现了,有些书上的#include命令写作#include <文件名>,但有时候又会出现#include "文件名".你会 ...

  5. C语言中 单引号与双引号的区别

    在C语言中,字符用单引号,字符串用双引号.在c1='a';中,'a'是字符常量,必须用单引号."a"表示字符串,包含两个字符,一个是'a',一个是'\0'. 用数组来存储字符串. ...

  6. c语言头文件中定义全局变量的问题

    c语言头文件中定义全局变量的问题 (转http://www.cnblogs.com/Sorean/) 先说一下,全局变量只能定义在 函数里面,任意函数,其他函数在使用的时候用extern声明.千万不要 ...

  7. php 单双引号的区别

    在PHP中,字符串的定义可以使用英文单引号' ',也可以使用英文双引号" ". 但是必须使用同一种单或双引号来定义字符串,如:'Hello World"和"He ...

  8. PHP中单引号与双引号的区别

    在PHP中,字符串的定义可以使用英文单引号' ',也可以使用英文双引号" ". 一般情况下两者是通用的.但双引号内部变量会解析,单引号则不解析. PHP允许我们在双引号串中直接包含 ...

  9. 【转】perl中尖括号运算符(<>)使用说明

    perl中尖括号运算符的用途分享,这里简单介绍下,方便需要的朋友 perl中<>运算符可以有如下的用途: 1)如果尖括号中间是文件句柄,尖括号运算符允许你读取文件句柄,比如<STDI ...

随机推荐

  1. HDU1811 并查集+拓扑排序

    题目大意: 判断是否能根据给定的规则将这一串数字准确排序出来 我们用小的数指向大的数 对于相等的情况下,将二者合并到同一个并查集中,最后抽象出来的图上面的每一个点都应该代表并查集的标号 #includ ...

  2. BZOJ 1225: [HNOI2001] 求正整数 高精度+搜索+质数

    题意:给定n求,有n个因子的最小正整数. 题解:水题,zcr都会,我就不说什么了. 因数个数球求法应该知道,将m分解质因数,然后发现 a1^p1*a2^p2....an^pn这样一个式子, (1+p1 ...

  3. 【Tomcat】Tomcat Connector的三种运行模式【bio、nio、apr】

    Tomcat Connector(Tomcat连接器)有bio.nio.apr三种运行模式 bio bio(blocking I/O,阻塞式I/O操作),表示Tomcat使用的是传统的Java I/O ...

  4. Linux下汇编语言学习笔记56 ---

    这是17年暑假学习Linux汇编语言的笔记记录,参考书目为清华大学出版社 Jeff Duntemann著 梁晓辉译<汇编语言基于Linux环境>的书,喜欢看原版书的同学可以看<Ass ...

  5. 对付 MySQL 的死连接,Sleep的进程的来源探究[转]

    当前的连接数:mysql> show status like '%Threads_connected%';+-------------------+-------+| Variable_name ...

  6. JVM 总结

    面试 java 虚拟机 jvm 基础 jvm Write Once Run EveryWhere >jar 包可以在任何兼容jvm上运行 >jvm 适配器 屏蔽掉底层差异 >内存管理 ...

  7. 动态演示冒泡排序java

    动态演示冒泡排序java //冒泡排序是一种简单的交换排序,基本思路,从数列左边开始扫描元素,在扫描过程中依次对相邻元素进行比较,将较大元素后移. public class NumberSort { ...

  8. 保持WCF服务端与客户端的长连接

    背景 客户端与服务端使用WCF建立连接后:1.可能长时间不对话(调用服务操作):2.客户端的网络不稳定. 为服务端与客户端两边都写“心跳检测”代码?不愿意. 解决 设置inactivityTimeou ...

  9. how to read openstack code : stevedore

    学习了WSGI/Paste deploy后,还需要对一些在openstack中一些package有一些了解,才能更好的理解openstack的代码 What is stevedore 我们在写代码的时 ...

  10. 实战c++中的vector系列--vector的一些异常

    今天就写一写vector的一些异常.能够捕捉的异常. out_of_range 相当于数组的越界了.vector会自己主动增大容量,可是假设索引超出了当前的size.就会引发异常. #include& ...