C语言为什么要区分.h和.c?为何不能在头文件里写定义?

您所在的位置:网站首页 c语言是什么开头的文件 C语言为什么要区分.h和.c?为何不能在头文件里写定义?

C语言为什么要区分.h和.c?为何不能在头文件里写定义?

2024-07-10 15:56| 来源: 网络整理| 查看: 265

原贴:https://blog.csdn.net/trap94/article/details/50602090

我们都知道,在写外部函数的时候,应该在源文件中写具体定义,而在对应的头文件中写申明,最后在执行文件中包含这个头文件就行了。

但到底为什么不能在直接在头文件里写定义呢?

一句话解释下:因为会产生重复定义的问题!

但我们还知道,我们还有#ifndenf这个东西,如果要问起来这东西是干啥用的,估计大家都知道这东西是用来防止源文件重复包含相同的头文件的,但我们用了这东西是不是表示就允许在头文件里写定义了呢?

准确的说:依然不可以,因为#ifndenf只解决了部分环节的重复定义问题!

########给新人科普##########

头文件中#ifndef的用法如下:

#ifndenf __XXXXX_H

#define __XXXXX_H

函数声明

#endif

其中ifndef(if not define)用来判断这个宏有没有定义过,如果没有定义过,说明这个头文件是第一次引用,那么就继续往下执行;如果这个宏定义过了,说明这个头文件已经被包含过了,直接跳到endif,也就是什么都不执行,就可以防止重复包含头文件了。

########################

那么为什么说#ifndef不能解决所有重复定义的问题呢?因为重复定义这个可能发生编译的不同环节,下面我们一个环节一个环节来分析。

第一个环节:预处理

这个环节做两件事,一把include的头文件内容进行替换,二是处理宏定义。不过这个环节并没有对语法进行检查,所以无论怎么重复定义,这个环节都不会报错的,只不过这个环节以后就没有include了,头文件的内容都替换上去了。

第二个环节:编译(汇编+编译)

这个环节是将源文件变成二进制的目标文件,也就是把.c变成.o(windows下是.obj),并且这个环节是会进行语法检查的,所以如果在某个头文件中定义了一个函数,然后源文件中又连续多次包含这个头文件的话,那么在编译阶段就会报错,例子如下所示:

因此我们需要利用#ifndef来避免重复包含相同的头文件(表面上看好像不会有人傻到像我上面这样连着写很多一样的include,但是我们知道头文件是可以嵌套包含的,如果a.h中包含着b.h,而如果你的.c文件又同时包含了a.h和b.h,一旦项目复杂了,这种情况是否就有可能发生了呢)所以使用#ifndef还是很有必要的。

ok,到目前为止,#ifndef成功地帮我们解决了在编译阶段的重复定义问题,不过它能做的也仅限于此了。

第三个阶段:链接

这是我之前一直都没有想通的一个地方,先看下面这个例子:

上面这个例子的头文件中使用了ifndef,但是最后还是出现了重复定义的问题,为什么呢?原因是在编译阶段,每个源文件都是独立编译的,他们会生成独立的.o文件,这些文件单独出来看的话是每个问题的,每个源文件都只有一次定义,因而编译通过,生成了main.o和file.o这两个目标文件,但这两个文件中各有一次定义,所以在链接阶段,把这个两个目标文件链接在一起的时候就变成有两次定义了,也就出现重复定义的问题了。

总结一下,ifndef可以解决编译阶段发生的重复定义问题,但不能解决链接阶段发生的重复定义问题,所以不要在头文件中作具体定义!

当然以上所说都是在头文件中进行了定义的情况,如果没有在头文件中作定义,而只是声明的话,那么,要是不讲就的话,哪怕不写ifndef都是可以的,因为只有重复定义会报错,重复声明是不会报错的。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3