头文件如何知道函数原型的实现位置?

lmi*_*asf 4 c linker compilation header-files

我有以下文件:

main.c中

#include <stdio.h>
#include "my_math.h"

int main()
{
    int a = 10, b = 5;
    add(a, b);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

my_math.h

int add(int a, int b);
Run Code Online (Sandbox Code Playgroud)

my_math.c

#include "my_math.h"
int add(int a, int b)
{
    return a + b;
}
Run Code Online (Sandbox Code Playgroud)

我知道使用#include "my_math.h"复制my_math.h文件的内容在调用它的文件中.但是,main.c文件如何执行add()函数呢?一开始我认为my_math.hmy_math.c应该匹配名称,但不是扩展名,但是我已经将名称从my_math.c更改为my_matho.c并且一切都像以前一样工作,所以我知道怎么知道这个函数的实现在哪里?

我使用以下命令编译:

gcc -g -O0 -Wall main.c my_math.c -o main
Run Code Online (Sandbox Code Playgroud)

还有一个问题是它与前一个命令相同:

gcc -g -O0 -Wall my_math.c main.c -o main
Run Code Online (Sandbox Code Playgroud)

所以这意味着我指示要编译的文件的顺序无关紧要?

Sou*_*osh 5

有两个不同的阶段,编译和链接。

  • 在编译过程中,编译器只需要知道函数的原型
  • 在链接期间,目标文件实际上是链接在一起的。

因此,在编译期间,不需要where部分。但是,在链接时,该函数应该存在于被链接在一起的目标文件之一中。

详细地说,这就是为什么我们看到,即使缺少头文件(函数的前向声明)但具有所有必需的目标文件,编译和链接也可能发生(显然有警告)(链接器实际上可以找到并链接所需的函数实现),但即使使用正确的头文件,如果您不提供包含实际定义的所需目标文件,链接器也会 对你尖叫 抛出错误。

  • @lmiguelvargasf [希望这会有所帮助](https://en.wikipedia.org/wiki/Forward_declaration)。基本上是你在`my_math.h` 中所做的。:) (2认同)

Uni*_*ant 5

编译器不知道.链接器确实如此.

每个源文件都编译为一个目标文件:

例如,main.c变为main.o,my_math.c变为my_math.o.

在编译main.c函数原型时my_math.h,告诉编译器会有一个int add(int a, int b);它可以调用的函数,但它没有关于这个函数的额外知识.

当链接器将main.o和my_math.o链接到可执行文件时,它会执行必要的重定位.