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的内容,发现可用的信息很少,要么长篇大 ...
随机推荐
- 使用离线部署32B模型实现OpenDeepWiki项目代码自动分析与文档生成
背景介绍 在企业环境中,我们经常需要对公司项目代码进行分析和文档生成.然而,考虑到代码的保密性,将代码上传至公共AI平台存在安全隐患.为解决这一问题,我们可以在公司内部GPU服务器上部署强大的大语言模 ...
- ASP.NET Core知识积累
1.[HttpGet(Name="xxxx")] 当在 ASP.NET Core 中的控制器中使用 [HttpGet(Name = "GetWeatherForecast ...
- Linux,yum错误,There are no enabled repos.(学习)
1.yum yum(全称为 Yellow dog Updater, Modified)是一个在Fedora和RedHat以及SUSE中的Shell前端软件包管理器.基於RPM包(RPM 是 Red H ...
- Django中的内置Tags
Dates {% now "m/d/Y" %} copyright {% now 'Y' as current_year %} 该tag也可以接受Django的date 变量,比如 ...
- codeup之求圆周率pi的近似值
Description 用如下公式 求圆周率PI的近似值,直到发现某一项的绝对值小于10-6为止(该项不累加). 要求输出的结果总宽度占10位,其中小数部分为8位. 程序中使用浮点型数据时,请定义为双 ...
- Docker基本使用方法
Docker 的基本使用方法 最近在尝试复现研究CVE,docker太方便了,学了下基本的使用方法,怕忘记,记于此处 1. 容器与镜像 镜像是一堆只读的文件. 容器 = 镜像 + 读写层 运行态的容器 ...
- 高德API获取省市区---python3实现
# -*- coding: utf-8 -*- """ Created on Thu Nov 4 15:40:25 2021 @author: 何双新 "&qu ...
- Qt的一个大坑:设置QPlainTextEdit和QTextEdit背景色
在工作中遇到一个需求,需要在播放器上显示英文字幕,当鼠标点击某个单词时, 可以显示该单词的中文含义. 播放器主窗口类直接继承自QGraphicsView,然后在其上创建一个透明的QPlainTextE ...
- 2023电赛E题代码
openmv: import sensor, image, time from pyb import LED, UART #import lcd import json, ustruct class ...
- `.NC`文件的读取与使用
.NC文件的读取与使用 前言 NetCDF(network Common Data Form)网络通用数据格式是一种面向数组型并适于网络共享的数据的描述和编码标准.目前,NetCDF广泛应用于大气科学 ...