为什么在已定义函数的源代码中添加头文件?

时间:2019-01-31 03:43:10

标签: c gcc include c-preprocessor header-files

例如,如果我有以下三个用C编写的文件:

hello.h

void hello (const char * name);

hello.c

#include "hello.h"
int
main (void)
{
hello ("world");
return 0;
}

hello_fn.c

#include <stdio.h>
#include "hello.h"
void
hello (const char * name)
{
printf ("Hello, %s!\n", name);
}

我知道将#include "hello.h"行添加到 hello.c 告诉编译器在外部文件(单独编译)期间将提供hello (const char * name)的定义, 但是我现在的问题是,为什么在hello_fn.c包含hello (const char * name)定义时将其添加到文件hello_fn.c中,我的意思是不会从外部提供它? < / p>

谢谢

1 个答案:

答案 0 :(得分:2)

这实际上是一个好习惯,因为编译器可以根据您的定义(在hello_fn.c中检查您的声明(在标头中)。

否则,将无法确保它们匹配。您可以轻松地输入:

void hello (int notCorrect) { ... }

放入C源文件中,它将很乐意独立地编译两个源文件,然后(取决于您在...位中实际执行的操作)在运行时异常失败。


例如,考虑以下文件:

hello.c:
    #include <stdio.h>
    #include "hello.h"
    int main(void) { hello(42); }
hello_fn.c:
    #include <stdio.h>
    //#include "hello.h"
    void hello(char *x) { puts(x); }
hello.h:
    int hello(int x);

这可以很好地编译,因为每个C源文件在内部都保持一致。 hello.c/hello.h对认为hello使用int,而hello_fn.c认为使用C字符串。

在运行时,我得到一个核心转储(1),因为值42不是有效的字符串地址。当我取消对include中的hello_fn.c行的注释时,编译器会(正确地)抱怨我的声明和定义不同(因为hello_fn.c/hello.h对现在不一致)。


最重要的是,标头中可能还存在 other (虽然在您的示例中不是),但标头中仅存在 。这通常是在调用方和被调用方之间共享的声明,例如类型,extern项,#define项等等。在头文件和源文件中分别声明几乎没有意义。


(1) 实际结果可能会有所不同,因为这是不确定的行为。

相关问题