摘自:https://mp.weixin.qq.com/s/4e8_0SK4mrInJq1dEy4lFQ

不管你是初学者还是高手,在学习了解C语言的时候,都学过include这个知识。

而我们最熟悉最常见的热知识,无非就这么几句话描述。

include就是包含头文件的意思。

而这个头文件,一般是系统头文件,第三方库的头文件,以及自定义用户头文件。

包含的形式,一般是在c文件的开头,进行include。

包含的形式编写则是:

#include <stdio.h>

#include <abc0.h>

#include “abc1.h”

其中,<> 包含和””包含的区别就是””会优先寻找当前目录是否存在该头文件,如果当前目录没有,则会在系统目录以及工程配置头文件包含目录寻找。

而<>则是会在系统目录以及工程配置包含目录寻找。

好了热知识讲完了。嗯,大家离C语言高手又进一步了。到这里,有时候在招聘面试一些新人的时候,他们回答这个问题,甚至都眼含高光,已然是一副编程高手的样子了。

有的人就会说,C语言的include了解到这里就行了呀。再深入的没必要呀。编程够用了呀。

那我们对这个include展开几个问题,看大家面试的时候,有没有遇到过,或者平时有没有思考过。

0 include既然是包含头文件,是怎么个包含的。

1 include 必须在文件的开头么,可以在文件任意位置,甚至结尾么。

2 include 只能包含.h 文件么,能包含.c文件么,能包含任意文本文件么。

3 include 可以重复包含么。

4如果a.h里包含b.h,同时b.h里包含a.h,会出现循环嵌套包含么。

Q

0 include既然是包含头文件,是怎么个包含的。

我们通常了解到的内容,是编译器会自动去寻找头文件,把头文件包含进来编译。

但具体是这怎么个包含法呢。

编译器,一般是先将c文件,编译成o文件,再将o文件经过一系列操作,变成可执行文件或者静态/动态库。

那么,编译器怎么知道头文件呢。

那就是在编译的时候,找到include关键字段。比如include “abc1.h”,编译器找到了abc1.h这个文件了,会怎么呢。

举个例子:

abc1.h文件内容为:

#define ABC  123

#define HAHAHAHA

就两行内容

main.c文件内容为:

#include “abc1.h”

int main()

{

int a=ABC;

return 0;

}

通过编译器的包含之后,假如会生成一个新的临时c文件,就是

tmp_main.c,内容为:

#define ABC  123

#define HAHAHAHA

int main()

{

int a=ABC;

return 0;

}

然后再编译这代码。

所以,include的包含,可以理解为,将include的文件里的内容复制,并粘贴在当前位置。

带着这个知识和理解,我们就可以继续回答下面的问题了。

AQ

1 include 必须在文件的开头么,可以在文件任意位置,甚至结尾么。

在上一个问题里,include的本质,就是将include的文件,在当前位置展开。那么,就很好理解了。

对于编译器来说,不去管include在哪个位置,都是执行同样的操作。

所以,include可以在文件任意位置的。

AQ

include 只能包含.h 文件么,能包含.c文件么,能包含任意文本文件么。

还是include的本质,既然是将对应的文件的文本内容在当前位置展开,就意味着,并不是只能include .h文件,也可以include .c 文件。只是如果一般来说,include .c文件,相当于把两个或者多个c文件,合并到一个c文件,好处就是只需要编译总的c文件,被包含的c文件可以不需要编译。

甚至也可以include 任意文本文件,include .txt文件,include .ini文件都没问题。

AQ

3 include 可以重复包含么。

可以重复包含的。

比如在main.c里这样写:

#include <stdio.h>

#include <stdio.h>

#include “abc1.h”

#include “abc1.h”

因为编译器不关心这么多,只需要检测到include,并展开相应的文件内容即可。

至于重复包含,是否会报错,具体就看头文件写的怎么样。

被了避免重复被包含出现错误,一般头文件会加宏定义。

比如abc1.h文件:

#define ABC  123

#define HAHAHAHA

加了宏定义之后这样:

#ifndef __ABC1_H__

#define __ABC1_H__

#define ABC  123

#define HAHAHAHA

#endif

一般加了#ifndef/#define/#endif之后,重复包含也不会有问题了。

还是建议养成良好编程习惯

AQ

如果a.h里包含b.h,同时b.h里包含a.h,会出现循环嵌套包含么

如果没有加#ifndef/#define/#endif的话,就会出现循环嵌套包含,编译的时候,会报错。

b.h:3:15: error: #include nested too deeply

有提示.h文件嵌套太深了。

所以,在编程习惯上,对于.h文件,要记得加#ifndef/#define/#endif,养成良好编程习惯。

C语言中include的冷知识——聊聊大家熟悉又陌生的include的更多相关文章

  1. C语言中 ln(以自然对数e为底) lg(以十为底) 以及logab(以a为底,b为真数)的相关知识

    总所周知,我们在高中学过对数函数,记作y=logax.下面是百度百科关于对数函数的描述: 对数的定义:一般地,如果ax=N(a>0,且a≠1),那么数x叫做以a为底N的对数,记作x=logaN, ...

  2. C语言中,头文件和源文件的关系(转)

    简单的说其实要理解C文件与头文件(即.h)有什么不同之处,首先需要弄明白编译器的工作过程,一般说来编译器会做以下几个过程: 1.预处理阶段 2.词法与语法分析阶段 3.编译阶段,首先编译成纯汇编语句, ...

  3. C语言中fgetc、fputc和getc、putc的区别是什么

    看书的时候,发现了这四个函数,想知道他们的不同.结果上网查发现很多人说fgetc.fputc的f代表的是file,就是这两个函数是和文件有关的!但是一看他们的函数声明,如下图: 发现他们的参数里面都有 ...

  4. C语言中.h和.c文件解析(很精彩)

    C语言中.h和.c文件解析(很精彩)   简单的说其实要理解C文件与头文件(即.h)有什么不同之处,首先需要弄明白编译器的工作过程,一般说来编译器会做以下几个过程: 1.预处理阶段 2.词法与语法分析 ...

  5. C语言中.h和.c文件解析

    整理自C语言中.h和.c文件解析(很精彩) Part.1(林锐<高质量C/C++编程>) 通过头文件来调用库功能.在很多场合,源代码不便(或不准)向用户公布,只要向用户提供头文件和二进制的 ...

  6. 转-C语言中.h和.c文件解析

    C语言中.h和.c文件解析(很精彩)   简单的说其实要理解C文件与头文件(即.h)有什么不同之处,首先需要弄明白编译器的工作过程,一般说来编译器会做以下几个过程:       1.预处理阶段 2.词 ...

  7. C语言中.h和.c文件解析(转载)

    转载:http://www.cnblogs.com/laojie4321/archive/2012/03/30/2425015.html   简单的说其实要理解C文件与头文件(即.h)有什么不同之处, ...

  8. C 语言中 setjmp 和 longjmp

    在 C 语言中,我们不能使用 goto 语句来跳转到另一个函数中的某个 label 处:但提供了两个函数——setjmp 和 longjmp来完成这种类型的分支跳转.后面我们会看到这两个函数在处理异常 ...

  9. c语言中time相关函数

    工作中遇到的函数: int seed = time(NULL); srand(seed); signal(SIGINT, stop); signal(SIGUSR1, sig_usr1); 搜time ...

  10. C语言中的static 详细分析

    转自:http://blog.csdn.net/keyeagle/article/details/6708077/ google了近三页的关于C语言中static的内容,发现可用的信息很少,要么长篇大 ...

随机推荐

  1. C++函数重载的一点问题

    问题 #include <iostream> #include <vector> enum A { Value = 1 }; void a(std::vector<int ...

  2. Java 删除目录下相同文件

    摘要:通过MD5算法对指定目录下的文件去重. 背景   之前写了一篇博客<Java判断两个文件是否相同>,介绍如何校验两个文件内容是否相同,但是,不适用于对目录下文件去重的场景,故对其进行 ...

  3. java LocalDateTime 加减当前时间

      LocalDateTime 可以对当前时间进行加减,在LocalDateTime类中,以plus打头的方法是增加某项时间,如plusDays的请求参数表示将要增加的天数,但是可以为负值:以minu ...

  4. Intellij IDEA插件Free Mybatis plugin

    Free Mybatis plugin这个Intellij IDEA里面的插件真的十分nice,不仅可以实现XML文件与Mapper接口相互跳转,还可以逆向生成mapper和类. 直接在IDEA插件搜 ...

  5. oracle的递归写法:地区层级

    前言 mysql的递归看我另一篇博文:https://www.cnblogs.com/daen/p/17252369.html 表结构 数据 查询子节点 示例 SELECT cx1.* FROM PH ...

  6. 2025AI元年,常见智能体盘点

    你好,小钗在医疗AI.教育AI.管理AI有丰富的经验 关注公众号,回复1,与我交个朋友吧 2025被成为国内AI应用元年,抛开各个公司正在自研的各种产品,有两类产品是比较红火的:Agent平台以及智能 ...

  7. 鸿蒙Next仓颉语言开发实战教程:设置页面

    仓颉语言商城应用的页面开发教程接近尾声了,今天要分享的是设置页面: 导航栏还是老样式,介绍过很多次了,今天不再赘述.这个页面的内容主要还是介绍List容器的使用. 可以看出列表内容分为三组,所以我们要 ...

  8. 野兽先辈带您学Opencv:介绍直方图,直方图均衡化,直方图计算,实战利用直方图计算蛋的面积

    欧,又是坑爹的opencv实验,它又来了额 实验要求: 1.输入三通道RGB直方图 2.直方图均衡化后输出图片及直方图 3.计算鸡蛋的面积(像素数) 首先什么是直方图? 横坐标是灰度,纵坐标是每一个灰 ...

  9. 函数使用十六:BAPI_GOODSMVT_CREATE

    *&---------------------------------------------------------------------* *& Report ZBAPI_GOO ...

  10. 华为发布伙伴SDK优选库,并推动SDK安全隐私新标准制定

    6月21日,在华为开发者大会2025<鸿蒙生态伙伴SDK论坛>上,华为与中国信通院标准所.鸿蒙生态伙伴代表上海CA.一砂.三未信安,共同宣布"鸿蒙生态伙伴SDK优选库" ...