我有以下文件:
的main.c
#include <stdio.h>
#include "my_math.h"
int main()
{
int a = 10, b = 5;
add(a, b);
return 0;
}
my_math.h
int add(int a, int b);
my_math.c
#include "my_math.h"
int add(int a, int b)
{
return a + b;
}
我知道使用#include "my_math.h"
将my_math.h文件的内容复制到调用它的文件中。但是,main.c文件如何执行add()函数呢?
一开始我认为 my_math.h 和 my_math.c 应该与名称匹配,但不能与扩展名匹配,但我已将名称从my_math.c更改为 my_matho.c ,一切都像以前一样工作,那么怎么知道C函数的实现在哪里?
我使用以下命令编译:
gcc -g -O0 -Wall main.c my_math.c -o main
另一个问题是它与前一个命令相同:
gcc -g -O0 -Wall my_math.c main.c -o main
所以这意味着我指示要编译的文件的顺序无关紧要?
答案 0 :(得分: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链接到可执行文件时,它会执行必要的重定位。
答案 1 :(得分:4)
有两个不同的阶段,编译和链接。
因此,在编译期间,不需要 where 部分。但是,在链接时,该函数应存在于一个链接在一起的目标文件中。
详细说明,这就是为什么我们看到,即使缺少头文件(函数的前向声明)但是包含所有必需的目标文件,编译和链接也会发生(显然有警告)(并且链接器实际上可以查找并链接所需的函数实现),但即使使用正确的头文件,如果您不提供包含实际定义的必需目标文件,链接器将向您尖叫 throw错误。