IT이야기

C 오류 : 함수에 대한 정의되지 않은 참조이지만 정의되어 있습니다.

cyworld 2021. 4. 2. 21:17
반응형

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;
  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. 하나를 제거해야하거나 제거해야합니다 (분명히 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) 만들 대안이 많이 있습니다. 나는 여기서 최소한의 고점에 도달했습니다.


최근에이 문제가 발생했습니다. 제 경우에는 확장명에 따라 각 파일에 사용할 컴파일러 (C 또는 C ++)를 선택하도록 IDE를 설정했고 .cC ++ 코드에서 C 함수 (즉, 파일에서) 를 호출하려고했습니다 .

.hC 함수에 대한 파일은 가드 이런 종류의에 싸여되지 않았습니다 :

#ifdef __cplusplus
extern "C" {
#endif

// all of your legacy C code here

#ifdef __cplusplus
}
#endif

추가 할 수도 있지만 수정하고 싶지 않았기 때문에 다음과 같이 내 C ++ 파일에 포함했습니다.

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

( Extern "C"효과에 대한 명확한 설명은 UncaAlby의 모자 팁 입니다.)


문제는 testpoint.c를 컴파일하려고 할 때 point.h가 포함되어 있지만 point.c에 대해 알지 못한다는 것입니다. point.c에에 대한 정의가 있으므로 point.c가 create없으면 컴파일이 실패합니다.

MinGW에 익숙하지 않지만 컴파일러에게 point.c를 찾도록 지시해야합니다. 예를 들어 gcc를 사용하면 다음과 같이 할 수 있습니다.

gcc point.c testpoint.c

물론 다른 사람들 이 지적했듯이 main하나만 가질 수 있으므로 함수 중 하나도 제거해야합니다 .


point.h의 함수 정의에 "extern"키워드를 추가합니다.

ReferenceURL : https://stackoverflow.com/questions/5559250/c-error-undefined-reference-to-function-but-it-is-defined

반응형