[c] include 문, 헤더 또는 소스를 어디에 넣을까요?

헤더 파일이나 소스 파일에 포함을 넣어야합니까? 헤더 파일에 include 문이 포함 된 경우 해당 헤더 파일을 내 소스에 포함하면 내 소스 파일에 내 헤더에 있던 모든 포함 된 파일이 포함됩니까? 아니면 내 소스 파일에만 포함해야합니까?



답변

헤더 자체에 필요한 경우에만 include를 헤더에 넣으십시오.

예 :

  • 함수는 type을 반환합니다 size_t. 그런 다음 #include <stddef.h>에서 헤더 파일.
  • 함수는 strlen. 그런 다음 #include <string.h>소스 파일입니다.

답변

수년 동안 이것에 대해 상당한 의견 차이가있었습니다. 한때 헤더 는 관련된 모듈에있는 내용 선언 하는 것이 전통적 이었기 때문에 많은 헤더에는 특정 요구 사항이 있습니다.#include 헤더 세트 (특정 순서로)를 . 일부 극도로 전통적인 C 프로그래머는 여전히이 모델을 따릅니다 (적어도 일부 경우에는 신뢰할 수 있음).

최근에는 대부분의 헤더를 독립형으로 만드는 움직임이 있습니다. 해당 헤더에 다른 것이 필요한 경우 헤더 자체가이를 처리하여 필요한 모든 것이 포함되도록합니다 (주문 문제가있는 경우 올바른 순서로). 개인적으로 저는 이것을 선호합니다. 특히 헤더의 순서가 중요 할 때 문제를 다시 해결하기 위해 그것을 사용하는 모든 사람을 요구하는 대신 한 번 문제를 해결합니다.

대부분의 헤더는 선언 만 포함해야합니다. 즉, 불필요한 헤더를 추가해도 (일반적으로) 최종 실행 파일에 영향을주지 않아야합니다. 최악의 경우 컴파일 속도가 약간 느려집니다.


답변

너의 #include 의 헤더 파일이어야하고, 각 파일 (소스 또는 헤더)해야 #include헤더는 필요한 파일. 헤더 파일은#include 필요한 최소한의 헤더 파일이어야하며 소스 파일은 소스 파일만큼 중요하지는 않지만 소스 파일도 있어야합니다.

소스 파일에는 헤더가 있습니다. #include#include 에는 최대 중첩 깊이까지 헤더와 해당 헤더 등이 있습니다 . 이것이 #include헤더 파일에 불필요한 s를 원하지 않는 이유입니다 . 소스 파일에 필요하지 않은 많은 헤더 파일이 포함되어 컴파일 속도가 느려질 수 있습니다.

이것은 헤더 파일이 두 번 포함될 수 있으며 문제가 될 수 있음을 의미합니다. 전통적인 방법은 foo.h 파일과 같이 헤더 파일에 “include guards”를 넣는 것입니다.

#ifndef INCLUDE_FOO_H
#define INCLUDE_FOO_H
/* everything in header goes here */
#endif


답변

제가 20 년 넘게 발전시킨 접근 방식은 이것입니다.

도서관을 고려하십시오.

여러 C 파일, 하나의 내부 H 파일 및 하나의 외부 H 파일이 있습니다. C 파일에는 내부 H 파일이 포함됩니다. 내부 H 파일에는 외부 H 파일이 포함됩니다.

컴파일러 POV에서 C 파일을 컴파일 할 때 계층 구조가 있음을 알 수 있습니다.

외부-> 내부-> C 코드

외부인 것이 제 3자가 라이브러리를 사용하는 데 필요한 모든 것이기 때문에 이것은 올바른 순서입니다. 내부적 인 것은 C 코드를 컴파일하는 데 필요합니다.


답변

헤더 파일 A #includes헤더 파일 B와 C이면 #includesA가 포함 하는 모든 소스 파일 도 B와 C를 얻습니다 #included. 전처리 기는 말 그대로 텍스트 대체를 수행 합니다. 파일 #include <foo.h>의 텍스트로 대체 한다고 말하는 텍스트가있는 곳이면 어디에서나 텍스트 대체를 수행 foo.h합니다.

#includes헤더 또는 소스 파일에 넣어야하는지에 대한 의견이 다릅니다 . 개인적으로 #includes는 기본적으로 모두 소스 파일에 넣는 것을 선호 하지만 다른 필수 헤더없이 컴파일 할 수없는 헤더 파일은#include 해당 헤더 자체가 합니다.

그리고 모든 헤더 파일은 여러 번 포함되는 것을 방지하기 위해 포함 가드를 포함해야합니다.


답변

일부 환경에서는 필요한 헤더 파일 만 포함 된 경우 컴파일이 가장 빠릅니다. 다른 환경에서는 모든 소스 파일이 동일한 기본 헤더 컬렉션을 사용할 수있는 경우 컴파일이 최적화됩니다 (일부 파일에는 공통 하위 집합 이외의 추가 헤더가있을 수 있음). 이상적으로는 여러 #include 작업이 효과가 없도록 헤더를 구성해야합니다. #include 문을 포함 할 파일의 include-guard에 대한 검사로 둘러싸는 것이 좋을 수 있지만,이 경우 해당 가드의 형식에 대한 종속성이 생성됩니다. 또한 시스템의 파일 캐싱 동작에 따라 대상이 완전히 #ifdef ‘되는 불필요한 #include가 오래 걸리지 않을 수 있습니다.

고려해야 할 또 다른 사항은 함수가 구조체에 대한 포인터를 사용하면 프로토 타입을 다음과 같이 작성할 수 있다는 것입니다.

void foo (struct BAR_s * bar);

범위 내에 있어야하는 BAR_s에 대한 정의없이. 불필요한 포함을 피하는 매우 편리한 접근 방식입니다.

추신-많은 내 프로젝트에서 모든 모듈이 #include 할 것으로 예상되는 파일이있을 것입니다. 여기에는 정수 크기에 대한 typedef와 몇 가지 일반적인 구조 및 공용체가 포함되어 있습니다.

typedef union {
  부호없는 긴 l;
  부호없는 짧은 lw [2];
  unsigned char lb [4];
} U_QUAD;

(예, 빅 엔디안 아키텍처로 이동하면 문제가 발생할 수 있지만 컴파일러가 공용체에서 익명 구조체를 허용하지 않기 때문에 공용체 내의 바이트에 대해 명명 된 식별자를 사용하려면 다음과 같이 액세스해야합니다. 다소 성가신 것처럼 보이는 theUnion.b.b1 등.


답변

포함 된 내용 만 사용하여 빌드 할 수 있도록 모든 파일을 만드십시오. 헤더에 포함이 필요하지 않으면 제거하십시오. 큰 프로젝트에서이 규칙을 유지하지 않으면 누군가가 헤더가 아닌 해당 파일의 소비자가 사용중인 헤더 파일에서 포함을 제거 할 때 전체 빌드를 깨뜨릴 수 있습니다.