컴파일 과정
- 컴파일의 역할
ο 문법 체크 + 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 같은 공식 헤더가드를 사용하기
'C │ C++ │ C# > C++' 카테고리의 다른 글
C++ Chapter 2.1 : 기본 자료형 소개 (0) | 2023.08.13 |
---|---|
C++ Chapter 1.5 : 네임스페이스, 전처리기 (0) | 2023.08.12 |
C++ Chapter 1.3 : 연산자, 기본적인 서식 맞추기, 선언과 정의의 분리 (0) | 2023.08.11 |
C++ Chapter 1.2 : 키워드 식별자 이름 짓기, 지역 범위 (0) | 2023.08.11 |
C++ Chapter 1.1 : 변수, 입출력스트림, 함수 (0) | 2023.08.10 |