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,养成良好编程习惯。

 

posted @ 2025-07-21 11:54  古锁阳关  阅读(38)  评论(0)    收藏  举报