programing

헤더 파일은 전체 프로그램에서 한 번만 포함됩니까?

lastmoon 2023. 9. 9. 10:06
반응형

헤더 파일은 전체 프로그램에서 한 번만 포함됩니까?

나는 이것이 흔한 질문이라는 것을 알지만 나는 아직도 그것을 완전히 이해할 수 없습니다.

여러 개의 다른 소스 및 헤더 파일에서 생성된 C 또는 C++ 프로그램에서 각 헤더 파일은 헤더 가드를 사용할 때 전체 코드에 한 번만 포함됩니까?

이전에 누군가가 헤더 파일(가드 포함)이 하나의 번역 단위에 한 번만 포함되지만 전체 코드에는 여러 번 포함된다고 말했습니다.이게 사실입니까?

전체 코드를 통해 한 번만 포함될 경우, 한 파일이 포함을 희망하고 전처리기에서 이미 포함된 것을 감지했을 때, 사용을 희망하는 파일이 이전에 포함된 코드의 위치를 어떻게 알 수 있습니까?

이 프로세스는 다음과 같습니다.

source           header   source header header
   \           /        \   |      /   /
    \         /          \  |     /   /
  PREPROCESSOR            PREPROCESSOR
       |                      |
       V                      V
 preprocessed code      preprocessed code
       |                      |
    COMPILER               COMPILER
       |                      |
       V                      V
  object code              object code
             \            /
              \          /
               \        /
                 LINKER
                   | 
                   V
               executable

전처리

#include이 첫 단계를 위해서 입니다.지정된 파일을 처리하고 결과를 출력에 삽입하도록 전처리기에 지시합니다.

한다면A를 포함B그리고.C,그리고.B를 포함C, 에 의 의 에 대한 전처리기의 출력A된할를다f의 처리된 가 포함됩니다.C두번이라.

중복 신고가 발생하기 때문에 문제입니다.해결책은 소스 코드가 포함되었는지 여부를 추적하는 전처리기 변수(일명 헤더 가드)를 사용하는 것입니다.

#ifndef EXAMPLE_H
#define EXAMPLE_H

// header contents

#endif

.EXAMPLE_H, 고그의을할다e다할을nesse지의고,그l가rednifndef/endif블록. 두 번째 블록은 건너뛸 것입니다.따라서 처리된 출력이 변경되고 정의는 한 번만 포함됩니다.

이는 매우 일반적이어서 일부 컴파일러가 구현하는 비표준 지시어는 더 짧고 고유한 전처리기 변수를 선택할 필요가 없습니다.

#pragma once

// header contents

C/C++ 코드의 휴대성과 사용할 헤더 가드를 파악할 수 있습니다.

헤더 가드는 각 헤더 파일의 내용이 번역 단위의 전처리 코드에 최대 한 번까지 존재하도록 보장합니다.

컴파일링

컴파일러는 당신의 전처리된 C/C++로부터 기계 코드를 생성합니다.

일반적으로 헤더 파일에는 실제 정의(일명 구현)가 아닌 선언만 포함됩니다.컴파일러에는 현재 정의가 누락된 모든 것에 대한 기호 테이블이 포함되어 있습니다.

링킹

링커는 개체 파일을 결합합니다.정의(일명 구현)를 기호 테이블에 대한 참조와 일치시킵니다.

두 개의 객체 파일이 정의를 제공하고 연결기가 하나를 선택할 수도 있습니다.이것은 실행 코드를 머리글에 입력한 경우에 발생합니다.이는 일반적으로 C에서는 발생하지 않지만 템플릿 때문에 C++에서는 매우 자주 발생합니다.

선언이든 정의든 헤더 "code"는 모든 객체 파일에 여러 번 포함되지만 링커는 이 모든 것을 병합하므로 실행 파일에 한 번만 존재합니다.(여러 번 나타나는 인라인 함수는 제외합니다.)

컴파일이 시작되기 전에 "헤더 파일"이 사전 프로세서에 의해 실제로 삽입됩니다.그냥 '대체'라고 생각해보세요#include

경비원이...

#ifndef MY_HEADER_H
#define MY_HEADER_H

// the "guarded" part of the header file is here...

#endif

... 교체 후에 실행됩니다.따라서 실제로 헤더는 여러 번 포함될 수 있지만 텍스트의 "보호된" 부분은 전처리기에 의해 한 번만 컴파일러에게 전달됩니다.

따라서 헤더에 코드 생성 정의가 있으면 컴파일 단위(일명 "모듈")의 개체 파일에 포함됩니다.동일한 헤더가#includeded는 여러 모듈에서 여러 번 나타납니다.

위해서static정의, 이는 전혀 문제가 되지 않습니다. 모듈(일명 파일 범위)을 넘어서는 볼 수 없기 때문입니다.프로그램-글로벌 정의의 경우, 이는 다르며 "여러 정의" 오류가 발생합니다.

참고: 이것은 대부분 C를 위한 입니다.C++의 경우 클래스 등이 여러 개의 전역 객체가 허용되는 시점에 추가적인 복잡성을 더해주기 때문에 상당한 차이가 있습니다.

적절한 포함 가드가 있는 헤더 파일은 번역 단위당 한 번만 포함됩니다.엄밀하게 말하면 여러 번 포함될 수도 있지만, 전처리기 사이의 부분이#ifndef그리고.#endif다음 포함 시 건너뛸 것입니다.올바르게 수행된 경우 파일의 전부(또는 대부분)가 됩니다.

번역 단위는 일반적으로 "소스 파일"에 해당하지만 일부 모호한 구현에서는 다른 정의를 사용할 수 있습니다.별도로 컴파일된 소스 파일에 동일한 헤더가 포함되어 있는 경우, 전처리기는 다른 파일이 이미 포함되어 있거나 다른 파일이 동일한 프로젝트의 일부라는 것을 알 방법이 없습니다.

여러 소스 파일(번역 단위)을 하나의 바이너리로 연결할 때 헤더가 표시된 선언, 템플릿, 함수 정의로만 구성되지 않으면 여러 정의에서 문제가 발생할 수 있습니다.inline, 또는 정적 변수 정의를 선택합니다.이를 방지하려면 헤더에 함수를 선언하고 다른 소스 파일과 함께 링크하는 별도의 소스 파일에 함수를 정의해야 합니다.

헤더 파일은 번역 단위별로 한 번씩 포함됩니다.각 번역 단위는 컴파일 과정을 위해 별도로 처리되기 때문에 프로그램당 여러 번 포함될 수 있습니다.이들은 연계 과정 중에 하나로 모여 완전한 프로그램을 구성합니다.

언급URL : https://stackoverflow.com/questions/30873206/header-file-included-only-once-in-entire-program

반응형