[C/C++] 헤더 내부에서의 헤더 인클루드

Gangsan O·2022년 3월 9일
0

C/C++

목록 보기
1/1

ar 명령어를 이용해 정적 라이브러리를 만들다가 고민이 생겼다. 라이브러리를 만들기 위해서는 오브젝트 파일이 필요한데, 오브젝트 파일로 변환될 소스파일들에서 필요한 헤더파일을 어디에 선언할지 고민이었다.

소스파일에서 필요한 헤더파일은 어디에 선언할까?

오브젝트 파일로 만들어질 소스파일에서 필요한 헤더파일은 해당 소스파일에 선언하는게 좋을까? 아니면 해당 소스파일의 함수를 모아둔 헤더파일에서 선언을 하고 그 헤더파일을 선언하는게 좋을까? 각각의 관점 마다 일리있는 이유가 있었다.

1. 소스파일에 선언하자

함수의 선언을 모아둔 헤더파일안에 각각의 함수(소스파일)들이 필요한 헤더파일(표준헤더, 사용자정의헤더 모두 포함)을 한번에 선언하면 해당 헤더가 필요 없는 소스파일에도 동일하게 컴파일하므로 빌드 시간이 늘어난다. 따라서 소스파일에서 필요한 헤더파일은 각각의 소스파일에 선언하는 것이 좋다.

예전의 모듈방식의 헤더 작성에서는 헤더를 한곳에 모아서 작성했지만 최근에는 컴파일 속도 뿐만 아니라 헤더 오더링 문제 때문에 소스파일에 선언하는 경향이 있다고 한다.

// 필요한 헤더파일을 각각의 소스파일에 선언
// my_func.c

#include <unistd.h>

size_t my_func(size_t arg)
{
  ...
}

-----------------------------------

//my_header.h

...
size_t my_func(size_t arg);
...

2. 함수를 모아둔 헤더파일에 선언하고 그 헤더파일을 소스파일에서 선언하자

빌드 타임은 늦어질 수 있지만 컴파일 이후 런타임 실행속도나 오브젝트 파일의 용량에는 영향을 미치지 않는다. 또한 자신이 속한 헤더파일을 다시 선언함으로써 해당소스파일이 어느 헤더파일에 속해있는지 알아 볼 수 있고, 매개변수 자료형이나 반환값의 자료형이 바뀌었을 경우 컴파일과정에서 잡아주기 때문에 안전장치가 될 수 있다.

// 필요한 헤더파일을 함수의 선언을 모아둔 헤더파일에 선언하고 그 헤더파일을 소스파일에 선언
// my_func.c
#include "my_header.h"

size_t my_func(size_t arg)
{
	...
}

-----------------------------------

//my_header.h
...
#include <unistd.h>
size_t my_func(size_t arg);
...

중론 : 각 소스파일에 선언하고 함수 모은 헤더파일도 선언하자

// my_func.c

#include <unistd.h>
#include "my_header.h"

size_t my_func(size_t arg)
{
	...
}

-----------------------------------

//my_header.h
...
size_t my_func(size_t arg);
...

함수 선언을 모아둔 헤더 파일에는 각 소스코드가 필요한 헤더를 포함시키지 않고 따로 소스코드에 각각 선언한다. 추가로 각각의 소스코드에 그 함수가 선언된 헤더 파일도 선언함에 따라 2번의 장점도 얻을 수 있다.

+) 추가

헤더파일에 선언된 자료형이 표준헤더를 필요로하면 헤더파일에 표준헤더 선언이 불가피하다. 따라서 각각의 소스파일에만 필요한 헤더파일을 선언하는 것은 완벽하게는 불가능하다.

// my_func.c

#include "my_header.h"

void my_func(void)
{
	...
}

-----------------------------------

//my_header.h
...
#include <unistd.h>
...
size_t another_func(size_t); // 선언에 표준헤더가 필요한 함수
void my_func(void); // 표준헤더가 필요 없는 함수
...
profile
감동 코딩

0개의 댓글