2011-07-05 5 views
2

헤더 파일에 #include이 있어야합니까?헤더 파일에 포함

저는 일반적으로 이런 종류의 계층 적 포함이 좋지 않다고 생각합니다. 당신이이 말 :

foo.h :

#include <stdio.h> // we use something from this library here 
struct foo { ... } foo; 

main.c를

#include "foo.h" 
/* use foo for something */ 
printf(...) 

날을 main.c의 구현을 변경, 당신은 더 이상 컴파일 것 foo.h를 사용하지 휴식을 취하고 <stdio.h>을 직접 추가해야합니다.

이 가진 대 :

foo.h 당신이 foo는을 사용하여 아무것도 중단하지 제거, 그러나 STDIO.H를 제거 중지 할 때

// Warning! we depend on stdio.h 
struct foo {... 

main.c를

#include <stdio.h> //required for foo.h, also for other stuff 
#include "foo.h" 

것 foo.h를 깨십시오.

#h 파일에서 #includes를 포함해야합니까?

+0

가능한 복제본 [C++에 대한 표준 #include 규칙이 있습니까?] (http://stackoverflow.com/questions/691079/is-there-a-standard-include-convention-for-c). 이것은 C++가 아니라 C이지만 원칙은 동일합니다. 좋은 충고가 많이 있습니다. http://stackoverflow.com/questions/181921/your-preferred-c-c-header-policy-for-big-projects는 다른 것입니다. –

답변

4

이 주제에 대한 두 가지 주요 철학을 요약했습니다.

내 생각에 (나는 이것이 모두 실제로 할 수있는 모든 것) 헤더는 가능한 한 자체 포함되어야한다는 것입니다. 나는 그 헤더를 사용할 수 있기 위해서 foo.h의 모든 의존성을 알 필요가 없다. 나는 또한 특정 순서로 헤더를 포함하는 것을 경멸한다.

그러나 개발자는 가능한 한 종속성을 없애기 위해 foo.h의 책임을 져야합니다. 예를 들어, foo.h 헤더는 가능한 경우 모든 경우에 stdio.h에 종속되지 않도록 작성해야합니다 (전달 선언을 사용하면 도움이 될 수 있음).

C 표준은 표준 헤더가 다른 표준 헤더를 포함하는 것을 금지하지만 C++ 표준은 포함하지 않습니다. 따라서 한 C++ 컴파일러 버전에서 다른 버전으로 이동할 때 설명하는 문제를 볼 수 있습니다. 예를 들어 <vector>을 포함하여 MSVC에서 <iterator>을 가져 왔지만 더 이상 MSVC 2010에서 발생하지 않으므로 <iterator>을 구체적으로 포함해야하기 때문에 이전에 컴파일 된 코드가 더 이상 필요하지 않을 수 있습니다.

그러나 C 표준은 두 번째 철학을 옹호하는 것처럼 보일 수 있지만 헤더가 다른 헤더에 의존하지 않으며 임의의 순서로 헤더를 포함 할 수 있어야한다는 점에 유의하십시오. 따라서 C 라이브러리의 구현자를 복잡하게 만들지 만 두 가지 장점을 모두 누릴 수 있습니다. 이 작업을 수행하기 위해 일부 농구를 뛰어 넘어야합니다 (특히 NULL 또는 size_t과 같은 여러 헤더 중 하나를 통해 가져올 수있는 정의를 지원하기 위해). 나는 C++ 표준을 초안 작성한 사람들이 분개장에 복잡성을 더하는 것이 더 이상 합리적이지 않다는 것을 결정했다고 생각한다. (나는 C++ 라이브러리 구현자가 '허점'을 어느 정도 활용하는지 모르겠다. MS가 이것을 강화하고있는 것처럼 보이지만, 기술적으로 필요하지 않더라도).

+0

''이 반복자로 작동하는 메소드를 선언한다면, 왜 ''을 가져 오면 안 될까요? 왜 사용자는이 작업을 수행해야합니까? 사용자가' '다음에''*을 실행하면 어떻게 될까요? –

+0

아마도 "tight up this"라고 말하지 말았어야했는데, 이것이 사용자에게 반드시 좋은 일임을 암시하는 것은 아닙니다. (이 ''을 시작). ' '이후 (또는 전에)' '을 가져 오는 데는 문제가 없습니다. 이미 포함되어 있다면,' '에 포함 된 모든 포함 가드가 두 번째로 문제를 일으키는 것을 방지합니다. –

+1

하지만 그게 나를 괴롭히는 이유입니다 : "#include '그냥 작동하겠다고 말하는 대신에, 사용자가 ''을 가져와' '전에해야하는 이유는 무엇입니까? 이것은 의도적으로 복잡성을 증가시키고 일종의 "순결"이라는 이름으로 버그를 도입하는 것과 같습니다. –

2

글쎄, 메인은 stdio의 경우 처음에는 "foo.h"에 의존해서는 안됩니다. 무언가를 두 번 포함시키는 데 아무런 해가 없습니다.
또한 foo 일 수도 있습니다. h은 실제로는 stdio이 필요하지 않습니다. 무엇보다 foo.c (구현)에 stdio이 필요합니다.

간단히 말하자면, 모든 사람들은 필요한 부분을 포함하고 include guards에 의존해야한다고 생각합니다. 코드 파일은 헤더를 필요로하지 않는 경우

+0

'stdio'는 임의의 선택 이었지만 struct {foo}는'stdio'에 정의 된 타입을 사용할 수 있습니다; main.c와 foo.c에 stdio.h와 foo.h를 포함시킬 필요가있다. – Tordek

+0

일반적인 예는 'size_t'유형이 필요한 헤더입니다. – caf

0

헤더 파일은 특정 헤더를 필요로하는 경우, 헤더 파일에 추가

#ifndef HEADER_GUARD_YOUR_STYLE 
#define HEADER_GUARD_YOUR_STYLE 

#include <stdio.h> /* FILE */ 
int foo(FILE *); 

#endif /* HEADER GUARD */ 

, 추가하지 마십시오

/* #include <stdio.h> */ /* removed because unneeded */ 
#include <stddef.h> /* NULL */ 
#include "header.h" 
int main(void) { 
    foo(NULL); 
    return 0; 
} 
0

왜 헤더에 해당하는 * .c 파일의 내용을 # 포함하지 않습니까?

1

수백 또는 수천 개의 헤더 파일이 포함 된 프로젝트에 들어가게되면이 파일을 사용할 수 없습니다. MyCoolFunction()의 프로토 타입을 포함하는 "MyCoolFunction.h"이라는 헤더 파일이 있고 그 함수가 구조체에 대한 포인터를 매개 변수로 사용한다고 가정 해 보겠습니다. 나는 MyCoolFunction.h을 포함하는 것이 필요한 모든 것을 포함하고, .h 파일을 보지 않고 그 기능을 사용하여 내가 무엇을 포함해야 하는지를 알 수 있다고 가정 할 수 있어야합니다.

2

내 일반적인 권장 사항은 다음과 같습니다

  • 파일이해야 #include 무엇을 필요로한다.
  • #include 뭔가 다른 것을 기대해서는 안됩니다.
  • #include 뭔가 다른 것이 필요할 수 있기 때문에 필요하지 않은 것이어야합니다.

진정한 시험은 이것이다 : 당신은 어떤 하나의 #include로 구성된 소스 파일을 컴파일하고 "더 main() 없다"이상 오류 또는 경고를 얻을 수 있어야합니다. 이 테스트를 통과하면 아무런 문제없이 #include 파일을 기대할 수 있습니다. 나는이를 테스트하는 데 사용할 "hcheck"라는 짧은 스크립트를 작성했습니다 :

#!/usr/bin/env bash 
# hcheck: Check header file syntax (works on source files, too...) 
if [ $# -eq 0 ]; then 
    echo "Usage: $0 <filename>" 
    exit 1 
fi 

for f in "[email protected]" ; do 
    case $f in 
     *.c | *.cpp | *.cc | *.h | *.hh | *.hpp) 
      echo "#include \"$f\"" > hcheck.cc 
      printf "\n\033[4mChecking $f\033[0m\n" 
      make -s $hcheck.o 
      rm -f hcheck.o hcheck.cc 
      ;; 
    esac 
done 

나는이 스크립트가 더 잘 할 수 있다는 것을 몇 가지가 있습니다 확신 해요,하지만 그것은 좋은 출발점이 될 것이다.

너무 많은 경우 헤더 파일에 거의 항상 해당 소스 파일이있는 경우 다른 방법은 관련 헤더를 소스 파일의 첫 번째 #include으로 지정하는 것입니다.

Foo.h :

#ifndef Foo_h 
#define Foo_h 

/* #includes that Foo.h needs go here. */ 

/* Other header declarations here */ 

#endif 

foo.c를 예를 들어

#include "Foo.h" 
/* other #includes that Foo.c needs go here. */ 

/* source code here */ 

또한 다른 사람들이 언급 한 Foo.h에서 "경비 포함"을 보여줍니다.

#include "Foo.h"을 먼저 입력하면 Foo.h은 (는) #include이어야합니다. 그렇지 않으면 컴파일 오류가 발생합니다.