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

uubf1zoe  于 2023-02-15  发布在  其他
关注(0)|答案(6)|浏览(162)

这只是一个简单的程序,但是我总是得到这个编译器错误。我使用的编译器是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);

这里是点。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;
}

这就是编译器的问题所在。我一直收到:
测试点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;
}

我不知道问题出在哪里。

r3i60tvu

r3i60tvu1#

你是如何编译和链接的?你需要指定两个文件,类似于:

gcc testpoint.c point.c

......这样它就知道要把这两个函数链接在一起。但是,使用现在编写的代码,你会遇到相反的问题:main的多个定义。您需要/想要删除一个(毫无疑问是point. c中的那个)。
在一个较大的程序中,你通常会分开编译和链接,以避免重新编译任何没有改变的东西。你通常会通过一个makefile来指定需要做什么,然后使用make来完成这项工作。在这种情况下,你会得到这样的结果:

OBJS=testpoint.o point.o

testpoint.exe: $(OBJS)
    gcc $(OJBS)

第一个只是一个目标文件名的宏,你可以用$(OBJS)来扩展它;第二个规则告诉make:1)可执行文件依赖于目标文件; 2)告诉它如何创建可执行文件,当/如果它与目标文件相比过时了。
大多数版本的make(包括MinGW中的make)都有一个内置的“隐式规则”,告诉他们如何从C源文件创建一个目标文件,通常大致如下:

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

这里假设C编译器的名称在一个名为CC的宏中(像CC=gcc这样隐式定义),并允许您在一个名为CFLAGS的宏中指定任何您关心的标志(例如,CFLAGS=-O3用于打开优化),而$<是一个特殊的宏,它可以扩展为源文件的名称。
通常将其存储在一个名为Makefile的文件中,要构建程序,只需在命令行输入make,它就会隐式查找一个名为Makefile的文件,并运行其中包含的任何规则。
这样做的好处是make会自动查看文件上的时间戳,所以它只会重新编译自上次编译以来发生了更改的文件(即,其中“.c”文件的时间戳比匹配的“.o”文件的时间戳更新)。
还要注意的是:1)当涉及到大型项目时,在如何使用make方面有很多变化,2)也有很多可供选择的make。

rsl1atfo

rsl1atfo2#

我最近遇到了这个问题。在我的例子中,我把我的IDE设置为根据每个文件的扩展名选择对每个文件使用哪个编译器(C或C++),我试图从C++代码调用一个C函数(IidoEe.从.c文件)。
C函数的.h文件没有被这种保护所 Package :

#ifdef __cplusplus
extern "C" {
#endif

// all of your legacy C code here

#ifdef __cplusplus
}
#endif

我本来可以添加的,但是我不想修改它,所以我只是把它包含在我的C++文件中,如下所示:

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

(Hat提示UncaAlby,了解他对effect of extern "C"的清晰解释。)

j13ufse2

j13ufse23#

我认为问题在于,当您尝试编译testpoint. c时,它包含point. h,但它不知道point. c。由于point. c具有create的定义,没有point. c将导致编译失败。
我不熟悉MinGW,但是您需要告诉编译器查找point.c。例如,对于gcc,您可以这样做:

gcc point.c testpoint.c

正如其他人所指出的,您还需要删除一个main函数,因为您只能有一个。

anauzrmj

anauzrmj4#

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

5jvtdoz2

5jvtdoz25#

我看到这个问题In c programming language, i keep getting this error
已经在这里回答,所以线程似乎关闭的答案。我不同意。这是不同的代码。
答案应该是我们不知道定制头文件“functions.h”中有什么。

MAPA m;
POSICAO heroi;

这些是函数,常量吗?如果这些是常量,应该在它们前面加上#define,而不是分号。

#define MAPA m 
#define POSICAO heroi

如果你打算原型化函数,因为后面有分号,那么你没有插入圆括号()。在这种情况下,MAPA和POSICAO是一些定制类型的函数,其内容应该在“Functions. h”中确定。
同样,也有可能你想从其他目录导入函数变量或者常量,在这种情况下你漏掉了这个词

extern MAPA m;
juud5qan

juud5qan6#

我在运行一个目录中的一堆.c文件时遇到了类似的问题,这些文件都链接到一个带有自定义函数原型的头文件。

$gcc -Wall -Werror -Wextra -pedantic -std=gnu89 *.c

获取这些错误:

/usr/bin/ld: /tmp/ccovH4zH.o: in function `_puts': 3-puts.c:(.text+0x2f): undefined reference to `_putchar'
/usr/bin/ld: 3-puts.c:(.text+0x51): undefined reference to `_putchar'
/usr/bin/ld: /tmp/ccGeWRqI.o: in function `main': _putchar.c:(.text+0xe): undefined reference to `_putchar'
/usr/bin/ld: _putchar.c:(.text+0x18): undefined reference to `_putchar'
/usr/bin/ld: _putchar.c:(.text+0x22): undefined reference to `_putchar'
/usr/bin/ld: /tmp/ccGeWRqI.o:_putchar.c:(.text+0x2c): more undefined references to `_putchar' follow
collect2: error: ld returned 1 exit status

注意:所有文件都链接到同一个头文件,其中包含所有函数声明。
我设法在gcc编译器中添加-c选项后成功编译,如下所示:
$gcc -墙-错误-额外-迂腐-标准= gnu 89-c *.c
此运行成功。
以防有人遇到同样的情况。

相关问题