2012-04-20 3 views
8

클래스 인터페이스 바로 위에있는 헤더 파일에서 C 함수를 정의하려고하면 빌드 오류가 발생합니다.헤더 파일에 일반 C 함수를 정의 할 수없는 이유는 무엇입니까?

하지만 구현 파일에서 동일한 작업을 수행하고 헤더에 선언을 할 때. 상황이 해결됩니다.

내가 알고 싶었는데 왜 헤더 파일에 enums, structs, 상수 NSString을 정의했는지, 왜 C 함수가 아닌지 알고 싶었 을까?

답변

14

이것은 C 링커 (또는 링크 편집기)의 작동 방식과 관련이 있습니다. C 컴파일러가 함수 정의를 가져 오면 해당 함수를 구현하는 어셈블러 코드를 준비하고 "this name with this function is where starting"이라는 링커에게 말한 심볼으로 표시합니다. 기호는 보통 밑줄과 함수 이름이 뒤에 오는 이름으로 지정됩니다 (예 : _printf.

헤더 파일에서 함수를 정의하면이 헤더를 가져 오는 .c 또는 .m 파일이 함수를 컴파일하고 컴파일러에서 동일한 기호를 내 보냅니다. 링커는 각 심볼의 인스턴스 하나만 찾길 원하므로 오류입니다.

이것은 #include 경비원의 존재와 관련이 없으며 #include 대신 #import을 사용하는 것과 관련이 없습니다. C 컴파일러는 개별 번역 단위에서 작동합니다. 개별 소스 파일을 의미합니다. 전처리 기 전략을 사용하면 동일한 헤더 파일을 단일 소스 파일에 두 번 포함시키지 않고 여러 파일에서 활동을 조정할 수 없습니다. 즉, 서로 다른 소스 파일에 동일한 헤더를 포함시키는 것이 유효하다는 것을 의미합니다. 즉, 다른 파일을 컴파일 할 때 동일한 기호를 (합법적으로) 포함 할 수 있습니다.

링크 편집기에서 컴파일 할 때 알 수없는 기호에 대한 참조를 모두 해결하는 것이이 편집기의 임무입니다. 동일한 심볼을 가진 객체 (컴파일되고 어셈블 된 번역 단위의 이름)를 동일한 아카이브, 공유 라이브러리 또는 실행 파일에 연결하려고하면 여기에 표시되는 오류가 발생합니다.

솔루션 :

  • 그냥 선언과 구현 파일에 정의, 헤더에 함수를 정의하지 마십시오 너는 이미이 작품을 발견했기 때문에.
  • 헤더에 함수를 정의하지만 코드의 한 위치에만 해당 헤더를 포함하십시오. 이는 설계상의 이유로 용납 될 수없는 경우가 많습니다.
  • 한정자 inline으로 헤더에 함수를 정의하십시오. 인라인 함수는 컴파일러에 의해 호출 된 함수로 복사되기 때문에 링커 심볼은 절대 전달되지 않습니다. 이것은 자신의 절충점이 있습니다. may wish to read more about.
+0

#include 대신 #import를 사용하면 파일을 한 번만 포함 할 수 있습니까? 그리고 .. #ifndef MYFILE_H #define MYFILE_H ... #endif) – Francesco

+1

@Francesco 질문에 감사드립니다. 짧은 대답은 전 처리기 가드가 멈추지 않는다는 것입니다. 링크 오류 발생). –

+0

하지만 .. 우리는 C 함수의 정의 또는 선언에 대해 이야기하고 있습니까? 왜냐하면 .. .h 파일에서 함수 정의로 시도하고 파일을 두 번 포함합니다. #include를 사용하면 함수의 "재정의"가 발생합니다. # import 또는 guard (모든 .h 파일에서)를 사용하면 오류가 발생하지 않습니다. – Francesco

관련 문제