C错误:未定义的函数引用,但它被定义

只是一个简单的程序,但我不断收到这个编译器错误。 我正在使用MinGW编译器。

这是头文件point.h

//type for a Cartesian point typedef struct { double x; double y; } Point; Point create(double x, double y); Point midpoint(Point p, Point q); 

这里是point.c

 //This is the implementation of the point type #include "point.h" int main() { return 0; } Point create(double x, double y) { Point p; px = x; py = y; return p; } Point midpoint(Point p, Point q) { Point mid; mid.x = (px + qx) / 2; mid.y = (py + qy) / 2; return mid; } 

这里是编译器问题的地方。我不断得到:

testpoint.c:对'create(double x,double y)'的未定义引用

虽然它是在point.c中定义的。

这是一个名为testpoint.c的单独文件:

 #include "point.h" #include <assert.h> #include <stdio.h> int main() { double x = 1; double y = 1; Point p = create(x, y); assert(px == 1); return 0; } 

我对这个问题可能会感到不知所措。

你怎么做编译和链接? 你需要指定两个文件,如下所示:

 gcc testpoint.c point.c 

…所以它知道把两者的function连接在一起。 然而,如果现在编写代码,则会遇到相反的问题: main多个定义。 你需要/想要消除一个(无疑是point.c中的一个)。

编辑:在一个更大的程序中,你通常分别编译和链接,以避免重新编译任何没有改变的东西。 您通常通过makefile指定需要完成的工作,并使用make来完成工作。 在这种情况下,你会有这样的事情:

 OBJS=testpoint.o point.o testpoint.exe: $(OBJS) gcc $(OJBS) 

第一个是对象文件名称的macros。 你得到$(OBJS)扩展。 第二个是告诉make 1)可执行文件依赖于目标文件的规则,2)告诉它如何在/如果与目标文件相比已经过期时如何创build可执行文件。

make的大多数版本(包括MinGW中的一个我都很确定)都有一个内置的“隐式规则”来告诉他们如何从C源文件创build一个目标文件。 它通常看起来大致是这样的:

 .co: $(CC) -c $(CFLAGS) $< 

这假设C编译器的名称是一个名为CC的macros(隐式定义,如CC=gcc ),并允许您在名为CFLAGS的macros中指定您关心的任何标志(例如, CFLAGS=-O3打开优化), $<是一个扩展到源文件名称的特殊macros。

您通常将其存储在一个名为Makefile ,然后构build您的程序,只需在命令行键入make 。 它隐式地查找一个名为Makefile ,并运行它包含的任何规则。

这样做的好处是make自动查看文件上的时间戳,所以它只会重新编译自上次编译以来发生更改的文件(即“.c”文件更多的文件最近的时间戳比匹配的“.o”文件)。

还要注意:1)在大型项目中,如何使用make有很多变化,2)也有很多替代品。 我只打这里的最高点。

我认为问题是,当你正在编译testpoint.c时,它包含了point.h,但它并不知道point.c。 由于point.c具有create的定义,没有point.c会导致编译失败。

我不熟悉MinGW,但你需要告诉编译器寻找point.c。 例如使用gcc你可能会这样做:

 gcc point.c testpoint.c 

当然,正如其他人指出的,你也需要删除你的mainfunction之一,因为你只能有一个。

将“extern”关键字添加到point.h中的函数定义中

我最近有这个问题。 在我的情况下,我让我的IDE根据其扩展名来select在每个文件上使用哪个编译器(C或C ++),而我试图从C ++代码调用C函数(即.c文件)。

C函数的.h文件没有包含在这种警惕之中:

 #ifdef __cplusplus extern "C" { #endif // all of your legacy C code here #ifdef __cplusplus } #endif 

我可以补充说,但我不想修改它,所以我只是将它包含在我的C ++文件中,如下所示:

 extern "C" { #include "legacy_C_header.h" } 

(由于他清楚地解释了外部“C”的效果,所以给UncaAlby一个小贴士 。)