C源文件的好处包括它自己的头文件

Che*_*hen 12 c declaration header-files

据我所知,如果源文件需要引用其他文件中的函数,那么它需要包含其头文件,但我不明白为什么源文件包含自己的头文件.头文件中的内容只是作为每个处理时间的函数声明被复制并粘贴到源文件中.对于包含其自己的头文件的源文件,这样的"声明"对我来说似乎没有必要,实际上,项目在从源文件中删除标题后仍然编译并链接没有问题,所以源文件的原因是什么包括它自己的头?

das*_*ght 19

主要好处是让编译器验证标头及其实现的一致性.你这样做是因为方便,不是因为它是必需的.绝对可以让项目在没有这种包含的情况下正确编译和运行,但从长远来看,它会使项目的维护变得复杂.

如果您的文件不包含自己的标题,则可能会意外地遇到函数的前向声明与函数定义不匹配的情况 - 可能是因为您添加或删除了参数,并且忘记更新标题.发生这种情况时,依赖于不匹配函数的代码仍然会编译,但调用会导致未定义的行为.让编译器捕获此错误要好得多,当源文件包含自己的头文件时会自动发生此错误.

  • @Chen当您从其他源文件中包含标头时,编译器只能访问原型.只要实际参数与原型匹配,编译器就不会抱怨,即使实现不同.编译器无法检查实现,因为它位于另一个文件中.当您从包含函数实现的文件中包含头时,编译器可以访问原型和实现,因此它可以检查另一个.如果原型与实际定义不匹配,编译器会抱怨. (3认同)
  • @Chen编译器不知道标头以任何方式与源文件相关。它关心的只是标头中的函数原型与源文件中的函数定义相匹配。当不匹配时,将触发错误。 (2认同)

Joh*_*ode 7

实际示例 - 假设项目中有以下文件:

/* foo.h */
#ifndef FOO_H
#define FOO_H
double foo( int x );
#endif

/* foo.c */
int foo( int x )
{
  ...
}

/* main.c */
#include "foo.h"

int main( void )
{
  double x = foo( 1 );
  ...
}
Run Code Online (Sandbox Code Playgroud)

请注意, 中的声明与;foo.h中的定义不匹配。foo.c返回类型不同。根据 中的声明,调用main.cfoo函数,假设它返回 a 。 doublefoo.h

foo.cmain.c彼此分开编译。由于调用中main.c声明,它编译成功。由于不包含,编译器不知道声明和定义之间的类型不匹配,因此它也能成功编译。foofoo.hfoo.cfoo.h

当您将两个目标文件链接在一起时,函数调用的机器代码将与函数定义的机器代码不匹配。函数调用期望double返回一个值,但函数定义返回一个int. 这是一个问题,尤其是当两种类型的大小不同时。最好的情况是你得到一个垃圾结果。

通过包含foo.hin foo.c,编译器可以在运行程序之前捕获这种不匹配。

而且,正如之前的答案中指出的那样,如果foo.h定义了 所使用的任何类型或常量foo.c,那么您肯定需要包含它。


Ed *_*eal 5

头文件告诉人们源文件可以做什么。

因此,头文件的源文件需要知道其义务。这就是为什么将其包括在内。

  • 您可以下载我的简明扼要。这是一个非常小的文件。 (5认同)
  • 我赞成,但是我还是很羡慕您的简洁性:-) (2认同)