[C++6] C++에서의 파일 분할

모옹·2023년 12월 18일
0

C++

목록 보기
6/10
post-thumbnail

6. 파일분할


6-1. C언어의 컴파일


6-1-1. 헤더파일

함수는 사용되기 전에 먼저 원형이 선언되어야 한다.

헤더파일
함수의 원형 및 함수와 관련된 다양한 정보를 가지고 있는 파일

확장자는 .h를 사용하고, #include 선행처리 지시자를 사용해 다른 파일에 포함시킬 수 있다.

표준 함수 역시 마찬가지이며, 표준 함수의 헤더파일인 표준 헤더 파일은 그 크기가 상당히 크다.
큰 헤더 파일을 포함하고 있다고 프로그램의 크기가 커지는 것은 아니다!
헤더파일의 내용은 실행 파일에 추가보다는 컴파일러가 실행 파일을 만드는 데에 사용하는 정보가 주류이다.
표준 헤더 파일은 표준 함수의 원형, 표준 함수의 매크로 상수, 표준 함수의 사용자 정의 타입 정의, 매크로 함수의 정의 정보를 포함하고 있다.

사용자가 자신만의 헤더파일을 작성해 쓸 경우, 여러 파일에서 같이 공유하는 외부 변수를 선언할 수 있다는 장점이 있다.


6-1-2. 분할 컴파일

하나의 실행 파일을 만들기 위해 소스 파일을 여러 개로 나누어 개발하는 방식

모듈
관련된 데이터와 함수를 하나로 묶은 단위로 프로그램의 구성 요소

하나의 소스 파일에 모든 함수를 작성하지 않고, 함수의 기능별로 모듈을 구성해서 독립된 파일에 저장하여 관리한다. 모듈은 개별적으로 컴파일되어, 링커에 의해 하나의 실행 파일로 만들어진다.

링크
최종적인 실행 파일의 생성을 위해서 접근하는 변수나 호출하는 함수가 어디에 있는지 서로 연결해주는 작업

분할 컴파일 방식에서 여러 개의 소스 파일 사이의 상호 참조는 전역 변수전역 함수만 가능하다.

extern
외부 파일에서 선언된 전역 변수를 참조하기 위해 사용하는 키워드

C 컴파일러는 프로그램에 등장하는 전역 변수를 해당 파일에서만 찾기 때문에 컴파일러에게 외부 파일에 존재하는 변수는 따로 알려줘야 한다.

변수 a, b를 선언하고 있는 sub.c 파일

int a = 10;
int b = 5;

sub.c 파일의 a, b를 참조하는 main.c 파일

#include "sub.c"

extern int a;
extern int b;

extern 키워드가 붙은 전역 변수는 컴파일 이후에 링크 때에 실제로 연결되게 된다.

static
분할 컴파일 방식에서 변수의 접근 영역을 해당 파일로만 한정시키고자 할 때, 선언하는 키워드


6-1-3. 조건부 컴파일

지정한 조건에 따라 코드의 일정 부분의 컴파일 여부를 지정할 수 있다.

#if 지시자
조건문과 비슷하지만 #endif 를 이용하여 조건부 컴파일의 끝을 명시해야 한다.

#if 조건식1
    컴파일할 명령문1

#elif 조건식2
    컴파일할 명령문2

#else
    컴파일할 명령문3

#endif

#ifdef 지시자
여러 헤더 파일을 합치다 보면 중복으로 선언된 함수나 변수가 있을 수 있다. 이 지시자를 이용하여 중복 선언의 가능성을 없앨 수 있다.

#ifdef 매크로이름
    컴파일할 명령문1

#elif 조건식
    컴파일할 명령문2

#else
    컴파일할 명령문3

#endif  

#ifndef 지시자
if not defined 라는 뜻으로 매크로가 정의되어 있지 않으면 컴파일 한다.

#ifndef 매크로이름
    컴파일할 명령문1

#elif 조건식
    컴파일할 명령문2

#else
    컴파일할 명령문3

#endif  

사용자 헤더 파일을 선언할 때에는 중복 선언을 피하기 위해 파일 내의 모든 내용을 #ifdef #ifndef #endif 지시자로 감싸는 것이 좋다.


6-2. C++ 파일분할

C++은 클래스 별로 헤더파일과 소스파일을 생성해서 클래스의 선언과 정의를 분리하는 경우가 많기 때문에 많은 수의 파일이 만들어지는데, 이 기준은 어떻게 될까?

.h 클래스의 선언을 담는다.
.cpp 클래스의 정의를 담는다.

class Car{
    ...
    void ShowCarState();
    void Accel();
    ...
};

void Car::ShowCarState(){ }
void Car:: Accel(){ }

int main(){
    Car A;
    A.Accel();
    A.ShowCarState();
}

예를 들어서 위의 코드에서

class Car{
    ...
    void ShowCarState();
    void Accel();
    ...
};

void Car::ShowCarState(){ }
void Car:: Accel(){ }

와 같은 클래스의 정의는 다른 문장의 컴파일에 필요한 정보를 가지고 있지 않다. 그렇다면, 컴파일 이후에 링커에 의해 하나의 실행파일로 묶이기만 하면 된다.

하지만,

int main(){
    Car A;
    A.Accel();
    A.ShowCarState();
}

와 같은 클래스의 선언은 컴파일 하는데에 있어서 반드시 필요하다.

인라인 함수의 경우, 컴파일 과정에서 함수의 호출문이 있는 곳에 함수의 몸체 부분이 삽입되어야 하므로, 헤더파일에 함께 넣어야 한다.


TCP SCHOOL - C 언어의 컴파일

<출처 : 윤성우의 열혈 C++ 프로그래밍>
위 책을 공부하며 정리한 내용입니다.

0개의 댓글