본문 바로가기
C │ C++ │ C#/C++

C++ Chapter 1.4 : 컴파일, 헤더 파일 만들기, 헤더 가드가 필요한 이유

by Pokaa 2023. 8. 12.
728x90
728x90
SMALL
컴파일 과정

 

  • 컴파일의 역할
    ο 문법 체크 + static 한 영역들 메모리 할당 일을 수행한다.
        ■ 프로그램이 실행되기 전에 미리 메모리에 할당되어 있어야 하는 부분들. 런타임 때 메모리가 결정되는
           부분들 말고!
  • 헤더 파일은 컴파일 되지 않는다.
    ο 헤더 파일은 include 한 cpp 파일 내에 전체 복사될 뿐이다.
  • cpp 파일들은 각각 독립적으로 컴파일 된다.
  • 그 다음에 컴파일이 완료된 cpp 파일들을 링킹 한다.

 

헤더 파일 만들기

 

  • 한 코드 파일에 모든 내용을 다 넣는건 좋지 않다.
    ο  #include "add.h" 해주면
        ■ add.h 헤더파일에 정의해 놓은 함수와 변수들을 마음대로 사용 가능하다.
        ■ add.h 헤더파일은 프로젝트와 동일한 위치에 있어야 한다.
            ■ 다른 위치라면 #include “myfolder/add.h” 이런식으로 상대 파일 경로를 써주어야 함
        ■ 단, add.cpp이 있다면 add.cpp도 같은 위치여야함.

 

헤더 가드

 

  •  헤더 파일 에는 함수의 프로토 타입만 쓰고
  •  헤더와 이름이 같은 cpp파일 에는 함수의 정의와 바디를 쓰고
  •  include한 cpp파일 에서 이 함수들을 사용한다.

ex)

  • add.h 라는 헤더 파일에 int add$($int x, int y$)$ 라는 함수의 프로토타입이 있는 상태
  • add.cpp 라는 코드 파일에 int add$($int x, int y$)$ 라는 함수의 바디가 있는 상태
  • 만약 이런 상황에서 add.cpp 코드 파일을 remove 시켰다면?
    ο 컴파일은 성공한다.
        ■ add.h 헤더 파일의  int add$($int x, int y$)$;  프로토타입만 가져와 검사하기 때문
    ο 단 add.cpp 파일은 무시되서 함수의 바디가 무시되기 떄문에 링킹 에러가 난다. 링킹은 실패함.
    문법상으론 OK지만 실행할 땐 문제가 생기는 것

cf)

  •  remove  : 파일 삭제는 아니고 그냥 이 파일을 무시하라는 의미. 빌드할 때 사용하지 않겠다는 의미.
  •  delete  : 파일 영구 삭제


헤더 가드를 사용하는 이유 : 헤더 재 정의를 방지 하기 위하여!

  • 보통 헤더파일엔 프로토타입만 적고 이름이 같은 cpp파일엔 바디를 적는 경우가 깔끔하지만
  • 그냥 헤더 파일 안에서 함수 바디까지 다 정의하는 경우도 있다.
    ο 이런 경우 생기는 문제
        ■ 똑같은 헤더 파일이 이중으로 불러와져 똑같은 바디가 두번 복사되는 일
          ex)
           add.h 

            ■ int add 함수의 바디까지 add.h 헤더파일 안에 다 정의했다면
int add (int x, int y ) 
{
	return x + y;
}

              work.h 
               ■ work.h의 work 함수 내부에서 add.h의 add((1,2)) 호출하는 상태라면

#include "add.h"

void work()
{
	add(1, 2); 
}

              main.cpp 
               ■ main.cpp 컴파일시
                   ■ cout << add((3, 4)) << endl;
                       ■  add.h 로부터 add함수정의&바디를 main.cpp에 복사해옴
                   ■ work();
                       ■ work.h → add함수, work함수정의&바디를 main.cpp에 복사해옴
                       ■ add ((1, 2)) 호출 → add.h → add함수정의&바디를 main.cpp에 복사해옴

#include "add.h"
#include "work.h"

int main()
{
	cout << add(3, 4) << endl;
	work();
}

                   ■ add함수 정의&바디가 main.cpp에 중복 복사된다.
                       ■ 똑같은 함수가 두번이나 정의되는 것이니 에러.
                        컴파일시  내부적으로 아래와 같은 상황이 되버린다.

int add (int x, int y ) // 바디가 두번 복사됨
{
	return x + y;
}

int add (int x, int y ) // 바디가 두번 복사됨
{
	return x + y;
}

void work()
{
	add(1, 2); 
}

int main()
{
	cout << add(3, 4) << endl;
	work();
}

               ■ 헤더 가드를 쓰면 이렇게 함수 바디 정의가 두번 중복되는 문제를 방지해준다.


헤더 가드 종류


1. #ifndef, #endif

  •  #ifndef 
    ο MY_ADD가 이미 정의 되어 있지 않다면 $($ if not define $)$
    ο 즉 아직 include 되지 않은 부분이라면
  •  #endif 
    ο #ifndef 부터 endif까지 이 범위의 복사를 허용해라.
  • 예시
    ο MY_ADD가 define 를 통해 정의되어 있으니
#ifndef MY_ADD
#define MY_ADD

int add(int a, int b)
{
	return a + b;
}
#endif

        ο 이미 이전에 include가 된 파일이라면 MY_ADD가 정의되어 있을테니
            ■ 아래 범위를 처리하지 않는다.
                ■ 이처럼 헤더 파일 재 정의를 막음 $($→ 함수 정의 2번 복사를 막음$)$

int add(int a, int b)
{
	return a + b;
}


2. #pragma once

  • 간단하게 한 줄이면 해당 헤더 파일 전체의 재정의를 막는다.
#pragma once

int add(int a, int b)
{
	return a + b;
}
  • C++공식 언어는 아니기 때문에 모든 컴파일러가 지원하는 것은 아니다.
    ο pragma once를 지원하지 않는 컴파일러라면 ifndef, endif 같은 공식 헤더가드를 사용하기
728x90
300x250
LIST