只是一个简单的程序,但我不断收到此编译器错误。我正在使用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;
p.x = x;
p.y = y;
return p;
}
Point midpoint(Point p, Point q) {
Point mid;
mid.x = (p.x + q.x) / 2;
mid.y = (p.y + q.y) / 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(p.x == 1);
return 0;
}
我不知道问题是什么。
答案 0 :(得分:80)
你是如何进行编译和链接的?您需要指定两个文件,例如:
gcc testpoint.c point.c
...因此它知道将两者的功能链接在一起。但是,根据现在编写的代码,您将遇到相反的问题:main
的多个定义。你需要/想要消除一个(毫无疑问是点c中的那个)。
在较大的程序中,通常需要单独编译和链接,以避免重新编译未更改的任何内容。您通常通过makefile指定需要完成的操作,并使用make
来完成工作。在这种情况下,你会有这样的事情:
OBJS=testpoint.o point.o
testpoint.exe: $(OBJS)
gcc $(OJBS)
第一个只是目标文件名称的宏。您可以使用$(OBJS)
进行扩展。第二个规则是告诉make 1)可执行文件依赖于目标文件,2)告诉它如何在/如果它与目标文件相比过时创建可执行文件。
大多数make版本(包括MinGW中的那个我很确定)都有一个内置的“隐式规则”来告诉他们如何从C源文件创建一个目标文件。它通常看起来大致如下:
.c.o:
$(CC) -c $(CFLAGS) $<
这假定C编译器的名称位于名为CC的宏中(隐式定义为CC=gcc
),并允许您在名为CFLAGS
的宏中指定您关心的任何标志(例如,{ {1}}启用优化)CFLAGS=-O3
是一个特殊的宏,可以扩展为源文件的名称。
您通常将其存储在名为$<
的文件中,要构建程序,只需在命令行键入Makefile
即可。它隐式查找名为make
的文件,并运行它包含的任何规则。
这一点的好处是Makefile
会自动查看文件的时间戳,因此它只会重新编译自上次编译以来已更改的文件(即文件所在的文件) .c“文件比匹配的”.o“文件具有更新的时间戳。
另请注意1)在涉及大型项目时,如何使用make有很多变化,2)还有很多替代品可供选择。我在这里只打出了最低点。
答案 1 :(得分:7)
我最近遇到过这个问题。在我的例子中,我的IDE设置为根据其扩展名选择在每个文件上使用哪个编译器(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"
}
(帽子提示UncaAlby以明确解释effect of extern "C"。)
答案 2 :(得分:6)
我认为问题是当你尝试编译testpoint.c时,它包含了point.h但它不知道point.c。由于point.c具有create
的定义,因此没有point.c将导致编译失败。
我不熟悉MinGW,但你需要告诉编译器寻找point.c。例如,使用gcc,您可以这样做:
gcc point.c testpoint.c
正如others指出的那样,你还需要删除一个main
函数,因为你只能有一个函数。
答案 3 :(得分:2)
将“extern”关键字添加到point.h中的函数定义