簡體   English   中英

C 錯誤:未定義對 function 的引用,但已定義

[英]C error: undefined reference to function, but it IS defined

只是一個簡單的程序,但我不斷收到此編譯器錯誤。 我正在使用 MinGW 作為編譯器。

這是 header 文件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:未定義對“創建(雙 x,雙 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;
}

我不知道問題是什么。

你是如何進行編譯和鏈接的? 您需要指定這兩個文件,例如:

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 中的那個)都有一個內置的“隱式規則”來告訴他們如何從 C 源文件創建目標文件。 它通常看起來大致是這樣的:

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

這假定 C 編譯器的名稱位於名為 CC 的宏中(隱式定義為CC=gcc ),並允許您在名為CFLAGS的宏中指定您關心的任何標志(例如, CFLAGS=-O3以打開優化)和$<是擴展為源文件名稱的特殊宏。

您通常將其存儲在一個名為Makefile的文件中,並且要構建您的程序,您只需在命令行中鍵入make 它隱式查找名為Makefile的文件,並運行它包含的任何規則。

這樣做的好處是, make自動查看文件上的時間戳,因此它只會重新編譯自上次編譯以來已更改的文件(即,“.c”文件具有更多最近的時間戳比匹配的“.o”文件)。

另請注意,1)在大型項目中如何使用 make 有很多變化,2)也有很多替代方案可供選擇。 我在這里只達到了最低限度的高點。

我最近有這個問題。 就我而言,我將 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 致敬,因為他清楚地解釋了 extern "C" 的效果。)

我認為問題在於,當您嘗試編譯 testpoint.c 時,它包含 point.h 但它不知道 point.c。 由於 point.c 具有create的定義,因此沒有 point.c 將導致編譯失敗。

我對 MinGW 不熟悉,但您需要告訴編譯器查找 point.c。 例如,使用 gcc 你可以這樣做:

gcc point.c testpoint.c

正如其他人指出的那樣,您還需要刪除一項main功能,因為您只能擁有一個。

在 point.h 中的函數定義中添加“extern”關鍵字

我在一個目錄中運行一堆 .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

注意:所有文件都鏈接到具有所有函數聲明的同一個頭文件。

在將 -c 選項添加到 gcc 編譯器后,我設法成功編譯,例如:

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

這樣運行成功。

以防萬一有人遇到同樣的情況。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM