C语言中include的冷知识——聊聊大家熟悉又陌生的include
摘自: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的更多相关文章
- C语言中 ln(以自然对数e为底) lg(以十为底) 以及logab(以a为底,b为真数)的相关知识
总所周知,我们在高中学过对数函数,记作y=logax.下面是百度百科关于对数函数的描述: 对数的定义:一般地,如果ax=N(a>0,且a≠1),那么数x叫做以a为底N的对数,记作x=logaN, ...
- C语言中,头文件和源文件的关系(转)
简单的说其实要理解C文件与头文件(即.h)有什么不同之处,首先需要弄明白编译器的工作过程,一般说来编译器会做以下几个过程: 1.预处理阶段 2.词法与语法分析阶段 3.编译阶段,首先编译成纯汇编语句, ...
- C语言中fgetc、fputc和getc、putc的区别是什么
看书的时候,发现了这四个函数,想知道他们的不同.结果上网查发现很多人说fgetc.fputc的f代表的是file,就是这两个函数是和文件有关的!但是一看他们的函数声明,如下图: 发现他们的参数里面都有 ...
- C语言中.h和.c文件解析(很精彩)
C语言中.h和.c文件解析(很精彩) 简单的说其实要理解C文件与头文件(即.h)有什么不同之处,首先需要弄明白编译器的工作过程,一般说来编译器会做以下几个过程: 1.预处理阶段 2.词法与语法分析 ...
- C语言中.h和.c文件解析
整理自C语言中.h和.c文件解析(很精彩) Part.1(林锐<高质量C/C++编程>) 通过头文件来调用库功能.在很多场合,源代码不便(或不准)向用户公布,只要向用户提供头文件和二进制的 ...
- 转-C语言中.h和.c文件解析
C语言中.h和.c文件解析(很精彩) 简单的说其实要理解C文件与头文件(即.h)有什么不同之处,首先需要弄明白编译器的工作过程,一般说来编译器会做以下几个过程: 1.预处理阶段 2.词 ...
- C语言中.h和.c文件解析(转载)
转载:http://www.cnblogs.com/laojie4321/archive/2012/03/30/2425015.html 简单的说其实要理解C文件与头文件(即.h)有什么不同之处, ...
- C 语言中 setjmp 和 longjmp
在 C 语言中,我们不能使用 goto 语句来跳转到另一个函数中的某个 label 处:但提供了两个函数——setjmp 和 longjmp来完成这种类型的分支跳转.后面我们会看到这两个函数在处理异常 ...
- c语言中time相关函数
工作中遇到的函数: int seed = time(NULL); srand(seed); signal(SIGINT, stop); signal(SIGUSR1, sig_usr1); 搜time ...
- C语言中的static 详细分析
转自:http://blog.csdn.net/keyeagle/article/details/6708077/ google了近三页的关于C语言中static的内容,发现可用的信息很少,要么长篇大 ...
随机推荐
- C++函数重载的一点问题
问题 #include <iostream> #include <vector> enum A { Value = 1 }; void a(std::vector<int ...
- Java 删除目录下相同文件
摘要:通过MD5算法对指定目录下的文件去重. 背景 之前写了一篇博客<Java判断两个文件是否相同>,介绍如何校验两个文件内容是否相同,但是,不适用于对目录下文件去重的场景,故对其进行 ...
- java LocalDateTime 加减当前时间
LocalDateTime 可以对当前时间进行加减,在LocalDateTime类中,以plus打头的方法是增加某项时间,如plusDays的请求参数表示将要增加的天数,但是可以为负值:以minu ...
- Intellij IDEA插件Free Mybatis plugin
Free Mybatis plugin这个Intellij IDEA里面的插件真的十分nice,不仅可以实现XML文件与Mapper接口相互跳转,还可以逆向生成mapper和类. 直接在IDEA插件搜 ...
- oracle的递归写法:地区层级
前言 mysql的递归看我另一篇博文:https://www.cnblogs.com/daen/p/17252369.html 表结构 数据 查询子节点 示例 SELECT cx1.* FROM PH ...
- 2025AI元年,常见智能体盘点
你好,小钗在医疗AI.教育AI.管理AI有丰富的经验 关注公众号,回复1,与我交个朋友吧 2025被成为国内AI应用元年,抛开各个公司正在自研的各种产品,有两类产品是比较红火的:Agent平台以及智能 ...
- 鸿蒙Next仓颉语言开发实战教程:设置页面
仓颉语言商城应用的页面开发教程接近尾声了,今天要分享的是设置页面: 导航栏还是老样式,介绍过很多次了,今天不再赘述.这个页面的内容主要还是介绍List容器的使用. 可以看出列表内容分为三组,所以我们要 ...
- 野兽先辈带您学Opencv:介绍直方图,直方图均衡化,直方图计算,实战利用直方图计算蛋的面积
欧,又是坑爹的opencv实验,它又来了额 实验要求: 1.输入三通道RGB直方图 2.直方图均衡化后输出图片及直方图 3.计算鸡蛋的面积(像素数) 首先什么是直方图? 横坐标是灰度,纵坐标是每一个灰 ...
- 函数使用十六:BAPI_GOODSMVT_CREATE
*&---------------------------------------------------------------------* *& Report ZBAPI_GOO ...
- 华为发布伙伴SDK优选库,并推动SDK安全隐私新标准制定
6月21日,在华为开发者大会2025<鸿蒙生态伙伴SDK论坛>上,华为与中国信通院标准所.鸿蒙生态伙伴代表上海CA.一砂.三未信安,共同宣布"鸿蒙生态伙伴SDK优选库" ...