컴파일러가 헤더 파일을 자체적으로 두 번 가져 오는 것을 피할 수없는 이유는 무엇입니까?


13

C ++가 처음입니다! 그래서 나는 이것을 읽고 있었다 : http://www.learncpp.com/cpp-tutorial/110-a-first-look-at-the-preprocessor/

헤더 가드

헤더 파일에는 다른 헤더 파일이 포함될 수 있으므로 헤더 파일이 여러 번 포함되는 상황이 발생할 수 있습니다.

따라서이를 방지하기 위해 전 처리기 지시문을 만듭니다. 하지만 난 잘 모르겠어요 - 왜 컴파일러는 그냥 ... 할 수 없는 두 번 같은 일을 가져?

헤더 가드는 선택 사항이지만 (양호한 모범 사례) 거의 두 번 가져 오기를 원할 때 시나리오가 있다고 생각합니다. 나는 그런 시나리오를 전혀 생각할 수 없지만. 어떤 아이디어?


MS 컴파일러 #pragma once에는 해당 파일을 한 번만 포함하도록 컴파일러에 지시하는 것이 있습니다.
코드 InChaos

답변:


27

새로운 언어로 표시되는 것처럼 가능합니다.

그러나 설계 결정은 몇 년 전 (C 컴파일러가 여러 개의 독립적 인 단계 일 때) 결정되었으며 이제 호환성을 유지하기 위해 이전 프로세서가 예상대로 이전 코드를 컴파일하도록 특정 방식으로 작동해야합니다.

C ++은 C에서 헤더 파일을 처리하는 방식을 상속함에 따라 동일한 기술을 유지했습니다. 우리는 오래된 디자인 결정을 지원하고 있습니다. 그러나 작동 방식을 변경하면 너무 많은 코드가 손상 될 수 있습니다. 이제 언어를 처음 사용하는 사용자에게 include guard를 사용하는 방법을 가르쳐야합니다.

헤더 파일에는 의도적으로 여러 번 포함시킨 몇 가지 트릭이 있습니다 (실제로 유용한 기능을 제공함). 패러다임을 처음부터 다시 디자인하면 파일을 포함하는 기본이 아닌 방법으로 만들 수 있습니다.


7

C와의 호환성을 유지하고 기존의 포장 시스템이 아닌 전처리기를 유지하기로 선택했다면 달리 표현력이 떨어질 것입니다.

나에게 떠오르는 한 가지는 API 인 프로젝트가 있다는 것입니다. 나는 두 개의 헤더 파일을 가지고 x86lib.hx86lib_internal.h. internal는 크기가 커서 "public"비트를 x86lib.h로 분리하여 사용자가 컴파일 시간을 추가로 확보 할 필요가 없었습니다.

이것은 의존성에 재미있는 문제를 일으켰습니다. 그래서 x86lib_internal에서 이런 흐름이 생겼습니다.

  1. 내부 전 처리기 정의 설정
  2. x86lib.h 포함 (내부 정의시 특정 방식으로 작동하는 것이 현명함)
  3. x86lib.h에서 사용되는 것들을 소개하고 소개하십시오.
  4. AFTER 프리 프로세서 정의 설정
  5. x86lib.h를 다시 포함하십시오 (이번에는 x86lib_internal의 요소에 의존하는 분리 된 AFTER 부분을 제외하고 모든 것을 무시합니다)

나는 그것이 최선의 방법이라고 말하지는 않았지만 내가 원하는 것을 달성했습니다.


0

자동 복제 헤더 제외의 한 가지 어려움은 파일 이름이 포함 된 대상에 대해 C 표준이 상대적으로 침묵한다는 것입니다. 예를 들어, 컴파일되는 기본 파일에 지시문이 포함되어 #include "f1.h"있고 #include "f2.h"해당 지시문에 대해 찾은 파일에 모두 포함되어 있다고 가정하십시오 #include "f3.h". 경우 f1.hf2.h다른 디렉토리에 있지만 검색하여 발견 된 후이 불분명 것, 경로를 포함 #include하는 파일 내 지시가 같은로드하도록 구성되었다 f3.h파일 또는 다른 사람을.

상대 경로를 포함한 포함 파일의 가능성을 추가하면 상황이 더욱 악화됩니다. 헤더 파일이 중첩 된 include 지시문에 상대 경로를 사용하고 제공된 헤더 파일을 변경하지 않으려는 경우 프로젝트 디렉토리 구조 내에서 여러 위치에 헤더 파일이 복제되어야 할 수도 있습니다. 해당 헤더 파일의 여러 물리적 사본이 존재하더라도 의미 상 단일 파일 인 것처럼 간주해야합니다.

는 IF #pragma once지시문을 수행 할 수있는 식별자 허용되는 once식별자는 이전-발생 하나 일치하는 경우 컴파일러는 파일을 생략해야한다는 의미로, #pragma once지시어, 그 의미가 명확한 것을; #include지시어가 #pragma once이전 파일과 동일한 태그가 지정된 파일을 로드 한다고 말할 수있는 컴파일러 는 파일을 다시 열지 않고 파일을 건너 뛰면 약간의 시간을 절약 할 수 있지만 파일을 건너 뛸지 여부에 따라 이러한 탐지는 의미 론적으로 중요하지 않습니다. 파일 이름이 일치하는 것으로 인식되었습니다. 그러나 나는 그런 식으로 작동하는 컴파일러를 모른다. 컴파일러가 파일이 패턴 #ifndef someIdentifier / #define someIdentifier / #endif [for that ifndef] / nothing following과 일치하는지 여부를 관찰 하고 위와 같은 #pragma once someIdentifier경우를 처리합니다.someIdentifier 정의 된 그대로, 본질적으로 좋습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.