1. ホーム
  2. c

[解決済み] Cエラー:関数への参照は未定義ですが、定義されています。

2022-03-03 14:50:58

質問

簡単なプログラムなのですが、このようなコンパイラーエラーが出続けています。コンパイラはMinGWを使用しています。

以下はヘッダーファイルです。 ポイント.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;
}

何が問題なのか、途方に暮れています。

解決方法は?

コンパイルとリンクはどのように行っているのでしょうか?両方のファイルを指定する必要があります、みたいな。

gcc testpoint.c point.c

...そうすれば、両方の関数を一緒にリンクすることができます。しかし、今のようなコードを書くと、逆の問題にぶつかることになります。 main . 1つ(おそらくpoint.cにあるもの)を削除する必要があります。

大きなプログラムでは、通常、変更されていないものを再コンパイルするのを避けるために、コンパイルとリンクを別々に行います。通常、makefile で何をすべきかを指定し、その際に make を実行します。この場合、次のようなものになります。

OBJS=testpoint.o point.o

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

1つ目は、オブジェクトファイルの名前をマクロ化しただけのものです。これを展開するには $(OBJS) . 2つ目は、1) 実行ファイルがオブジェクトファイルに依存していること、2) オブジェクトファイルと比較して古い場合/古い場合に実行ファイルをどのように作成するかをmakeに指示するためのルールです。

ほとんどのバージョンのmakeは(MinGWのものも含めて)、Cソースファイルからオブジェクトファイルを作成する方法を伝えるために、組み込みの"暗黙のルール"を持っています。これは通常、おおよそ次のようなものです。

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

これは、Cコンパイラの名前がCCというマクロ(のように暗黙のうちに定義されている)にあると仮定しています。 CC=gcc という名前のマクロで、気になるフラグを指定することができます。 CFLAGS (例, CFLAGS=-O3 で最適化をオンにする)と $< は、ソースファイル名に展開する特殊なマクロです。

という名前のファイルに保存するのが一般的です。 Makefile を入力し、プログラムをビルドします。 make をコマンドラインで実行します。という名前のファイルが暗黙のうちに探されます。 Makefile そして、そのルールに含まれるすべてのルールを実行します。

これの良いところは make は自動的にファイルのタイムスタンプを調べるので、前回コンパイルしたときから変更されたファイルだけを再コンパイルします(つまり、".c" ファイルのタイムスタンプが、一致する ".o" ファイルよりも新しいファイルです)。

また、1) 大きなプロジェクトになると、makeの使い方にはたくさんのバリエーションがあること、2) makeの代わりとなるものもたくさんあること、に注意してください。2)makeの代替ソフトもたくさんある。