ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 빌드 과정과 #include의 역할 이해하기
    Programming🧑‍💻/Cpp 2025. 2. 12. 14:52

    빌드 과정 이해하기 

    cpp 프로그램이 실행 파일이 되기까지는 크게 세 단계를 거칩니다. 

    1. 전처리(Preprocessing) 단계

    전처리기는 실제 컴파일이 시작되기 전에 소스 코드를 다듬는 작업을 수행합니다.

    #으로 시작하는 모든 지시문(#include, #define 등)을 처리하는 것이 바로 이 단계입니다.

    이때 #include 지시문을 만나면, 해당 파일의 내용을 그 자리에 그대로 복사해 넣습니다.

    2. 컴파일(Compilation) 단계

    전처리된 소스 코드를 기계어로 변환하는 단계입니다.

    각각의 .cpp 파일은 독립적으로 컴파일되어 목적 파일(.obj 또는 .o)이 됩니다.

    3. 링크(Linking) 단계

    여러 개의 목적 파일들을 하나로 모아서 실행 파일을 만드는 단계입니다.

    각 파일에서 사용된 함수나 변수의 실제 위치를 연결해줍니다.

     

    #include의 역할과 작동 방식 

    #include는 마치 "이 자리에 다른 파일의 내용을 복사해서 붙여넣으세요"라고 지시하는 명령어입니다.

    // math.h
    int add(int a, int b);
    // main.cpp
    #include "math.h"
    int main() {
        int result = add(5, 3);
        return 0;
    }

     

    전처리기는 위 코드를 다음과 같이 변환합니다. 

    // main.cpp (전처리 후)
    int add(int a, int b);  // math.h의 내용이 여기로 복사됨
    int main() {
        int result = add(5, 3);
        return 0;
    }

     

    헤더 파일 대신 cpp 파일을 직접 #include 하면 안되는 이유

    다음과 같이 헤더 파일 math.h를 사용하지 않고 math.cpp를 직접 #include 하는 경우

    // math.cpp
    int add(int a, int b) {
        return a + b;
    }
    
    // main.cpp
    #include "math.cpp"
    int main() {
        int result = add(5, 3);
        return 0;
    }
    
    // other.cpp
    #include "math.cpp"
    void someFunction() {
        int value = add(10, 20);
    }

     

    1. 전처리 과정 : Cpp 컴파일러는 #include 지시문을 만나면 해당 파일의 내용을 그대로 복사해 붙여 넣습니다. 따라서 컴파일 후에는 실제로 다음과 같은 상태가 됩니다.

    // main.cpp 컴파일 후
    int add(int a, int b) {    // math.cpp의 내용이 여기로 복사됨
        return a + b;
    }
    int main() {
        int result = add(5, 3);
        return 0;
    }
    
    // other.cpp 컴파일 후
    int add(int a, int b) {    // math.cpp의 내용이 여기도 복사됨
        return a + b;
    }
    void someFunction() {
        int value = add(10, 20);
    }

     

    2. One Definition Rule (ODR) 위반 : CPP의 ODR은 함수나 변수가 프로그램 전체에서 단 한 번만 정의되어야 한다고 규정합니다. 위 코드에서는 add 함수가 두 번 정의되어 이 규칙을 위반하게 됩니다.

     

    3. 링커 단계에서 문제 발생 : 컴파일러는 각 소스 파일을 개별적으로 컴파일하기 때문에 컴파일 단계에서는 문제가 발생하지 않습니다. 하지만 링커가 오브젝트 파일들을 하나의 실행 파일로 합치려고 할 때, add 함수의 정의가 중복되어 있어서 어떤 정의를 사용해야 할지 알 수 없게 됩니다. 이로 인해 링크 에러가 발생합니다.

     

    위와 같은 문제가 발생하지 않기 위해서 헤더 파일을 이용해 다음과 같이 코드를 작성해야합니다. 

    // math.h
    #ifndef MATH_H
    #define MATH_H
    
    int add(int a, int b);  // 함수 선언만 헤더 파일에 포함
    
    #endif
    
    // math.cpp
    int add(int a, int b) {  // 실제 함수 정의는 cpp 파일에 작성
        return a + b;
    }
    
    // main.cpp와 other.cpp
    #include "math.h"  // cpp 파일이 아닌 헤더 파일을 포함

     

     

    • 함수의 선언은 헤더 파일을 통해 여러 곳에서 공유될 수 있습니다.
    • 함수의 정의는 cpp 파일에 단 한 번만 존재하게 됩니다.
    • #ifndef (if not define)가드를 통해 헤더 파일이 여러 번 포함되는 것을 방지할 수 있습니다.

     

    'Programming🧑‍💻 > Cpp' 카테고리의 다른 글

    서브 루틴과 코루틴  (0) 2025.02.13
    Macro가 뭘까?  (0) 2025.02.12
    헤더파일은 뭐고 왜 필요한가?  (0) 2025.02.12
    L-value와 R-value  (0) 2025.02.06
    함수 호출시 매개변수 전달 방법 3가지  (0) 2025.02.05

    댓글

Designed by Tistory.