12

因此,我在 Head First C 中继续学习,我们正在学习如何将多个文件一起编译的一章。其中之一是encrypt.c

#include "encrypt.h"


void encrypt(char *message)
{
  char c;
  while (*message) {
   *message = *message ^ 31;
   message++;
  }
}

encrypt.h文件以分号结尾重复第一行,那我为什么需要它?我明白为什么在定义函数之前我需要头文件来解决使用函数的问题,所以我可以理解 #include 它在使用的文件中encrypt.c,但为什么我需要它在里面encrypt.c?这只是那些“因为”原因之一吗?

4

6 回答 6

19

如果 的内容encrypt.c完整显示,则不需要标题。但包含它仍然是一个好主意,因为:

  1. 如果文件中的一个函数使用另一个函数,那么定义的顺序很重要,因为被调用者必须在调用者之前定义。甚至可以有两个函数 A 和 B,其中每个函数调用另一个函数,在这种情况下,如果没有至少一个前向声明,您将无法编译代码。包含带有前向声明的标头可以解决这些问题。
  2. 像您的客户端代码一样使用标头是让编译器指出前向声明中的签名与实际函数定义之间的差异的好方法。如果未被检测到,此类问题可能会导致运行时出现“有趣”的行为,并导致很多麻烦。
于 2013-08-25T21:06:06.537 回答
6

你是对的,如果这都是encrypt.h声明,你不需要将它包含在.c文件中。

你主要是为了保持一致性。

于 2013-08-25T21:05:49.657 回答
5

想象一下,您将 encrypt.c 更改为void encrypt(char *message, int i) { }

如果您不包含 encrypt.h,您将不会注意到应用程序中的其他文件尚未更新以传递新参数。如果您同时更新 encrypt.h 和 encrypt.c,编译器可以为您进行检查。

于 2013-08-25T21:09:16.080 回答
2

这是很好的风格。有时,具有函数实现的 C 文件和具有函数用法的 C 文件共享公共声明 - 类型/结构,这共享 H 文件中的声明位置。例如。

[enc.h]
typedef enum {S,F} Res;
EN encode();

[enc.c]
#include "enc.h"
Res encode() { ... }

[other.c]
Res res;
res = encode();
于 2013-08-25T21:16:07.063 回答
0

然后将头文件包含在另一个 *.c 文件中,编译器以这种方式知道其他任何地方都是函数定义。

这就像:

#include <stdio.h>

int main (void)
{
   afun();
   return 0;
}

void afun (void)
{
   printf("hello\n");
}

现在编译器不知道如何处理主函数中的 afun() 。因为它没有被定义。所以它会导致编译器错误。

因此,您在开头添加声明或在第一次使用之前添加声明:

#include <stdio.h>

void afun(void);

int main (void)
{
   afun();
   return 0;
}

void afun (void)
{
   printf("hello\n");
}

知道编译器知道 afun 的声明,并希望在其他地方定义该函数。使用头文件可以使用预编译的 c 代码。编译器唯一需要的是函数的声明。

于 2013-08-25T21:23:17.080 回答
0

它正在对功能进行原型设计

http://en.wikipedia.org/wiki/Function_prototype

于 2013-08-25T21:07:19.070 回答