F.R.I.D.A.Y.

헤더파일 만들기 본문

DEV/C C++

헤더파일 만들기

F.R.I.D.A.Y. 2019. 1. 24. 10:15
반응형

 C/C++ 를 배울 때 꼭 하나씩 집어넣는 헤더파일이 있다.


#include <stdio.h>



 #include(전처리기)를 통해 [ stdio ]라는 헤더를 읽어들이는 것인데, 헤더파일에 대해 알아보자.



1. 헤더파일

  Wiki

 C/C++ 프로그리밍 언어에서, 컴파일러에 의해 다른 소스파일에 자동으로 포함된 소스코드의 파일이다.


 라고 나와 있다. 이미 만들어둔 코드들(함수, 전역 변수 등 | 라이브러리 포함)을 지금 만들고 있는 코드에서 사용할 수 있도록 미리 선언해둔 파일이다.


 우리가 주로 *.c 나 *.cpp 파일에 코드를 작성하는데, 조금 규모가 커지만 소스를 여러 파일에 두고 관리한다. 수정된 부분만 새로 컴파일해 컴파일 시간을 단축시키기 위한 방법으로 말이다. 그러다 헤더 파일에 대해 알게 되는데, 헤더 파일은 *.c나 *.cpp 파일의 인적사항을 기록한 서류와 비슷하다고 보면 된다.


 헤더 파일은 소스 파일에 선언된 전역 변수나, 함수의 원형을 작성해 사용자(다른 프로그램)가 헤더 파일만 보고 소스 파일에 존재하는 변수나 함수를 이용할 수 있도록 하는 것이 목적이 된다.

 소스파일 자체를 넘기면 기술이 유출되는것이 되어버리기 때문에 소스코드는 일반적으로 라이브러리를 만들거나 목적 파일을 만들고, 소스 파일의 구조를 가진 헤더 파일과 함께 전달한다.



2. 구조

 헤더 파일과 소스 파일은 아래의 구조로 연결된다.


main.c


#include "A.h"

int main(void){
    ...
    return 0;
}



A.h


#ifndef __HEADER_A_
#define __HEADER_A_

void Function1();
void Function2();
...

#endif

A.c


#include "A.h"

void Function1(){
    ...
}

void Function2(){
    ...
}



 즉, 헤더 파일은 다른 헤더 파일을 인클루드하긴 하지만 소스 파일( *.c *.cpp 등)은 인클루드 하지 않는다. 또한, 소스 파일과 소스 파일의 구조를 담아 놓은 헤더파일의 이름은 같다[각주:1].



3. 헤더 가드(Header Guard)

 stdio 헤더 파일의 내용을 살펴보면 처음에 아래와 같은 구조를 띤다.


 line 01 - 07 : 주석

 line 08 - 10 : 전처리기

 ...


 여기서 주의 깊게 살펴볼 내용은 line 8부터 10까지, 흔히 헤더 가드라고 불리는 전처리 작업이다.


 처음 헤더를 만들려고 하면 이런 실수를 한다.


 A 헤더가 B와 D 헤더를 포함하는데, D 헤더가 A 헤더를 호출하는 재귀 현상을 가진다. 이러한 구조의 문제는 읽음을 끝낼 위치를 정할 수 없다는 것이다.

 따라서, C/C++에서는 이러한 문제를 해결하기 위해 헤더 가드라는 기술을 이용했다. 뭔가 새로운 기술이 아니라 이미 존재하는 전처리기를 이용한 기술이다.


 #define은 치환을 위한 기술로 주로 사용되지만, 특성은 재 선언할 수 없다는 점이다[각주:2]. 즉, 고유하다. 이 특성을 이용해 전처리 기술을 이용한다.


 #ifndef는 특정 전처리 상수가 선언이 되었는지를 판단한다. 선언이 되었으면 false를, 선언되지 않았다면 true를 의미하며 true일 경우 짝이 맞는 #endif 까지를 읽어들인다[각주:3].


 이러한 특성으로 이미 선언된 변수/함수가 다시 읽어지지 않도록 처리를 진행한다.


 비주얼 스튜디오의 컴파일러 MSVC는 이러한 전처리기를 #pragma를 이용해 처리할 수 있도록 했는데, 코드는 아래와 같다.


#pragma once
// 해당 파일을 한 번만 읽어들게 하는 전처리기


 #pragma[각주:4] 자체는 C/C++의 표준 전처리기가 맞지만, #pragma once의 once는 MSVC에서 선언된 전처리 명령어라서 다른 컴파일러에서는 호환이 되지 않는다. 따라서 컴파일러에 구애받지 않고 컴파일을 진행하기 위해서는 #define을 이용한 헤더 가드 기술을 사용해야한다.

 다만, 진행하는 프로젝트가 MSVC에서만 컴파일한다는 확신이 있다면 #pragma once를 이용하는 것이 컴파일 시간이 더 적게 걸린다고 한다.


참고

>> https://kldp.org/node/46662#comment-171458

  1. A.c와 A.c의 구조를 담고 있는 A.h는 이름이 A로 같다. [본문으로]
  2. #undef로 삭제한 경우 제외 [본문으로]
  3. 즉, #ifndef 안에 새로이 #ifndef를 선언할 수 있다. [본문으로]
  4. 각 컴파일러마다 고유 기능을 설정하는데 사용하는 표준 전처리기. [본문으로]
728x90
반응형

'DEV > C C++' 카테고리의 다른 글

Q strlen 구현하기  (0) 2019.01.25
NULL 널문자 0  (0) 2019.01.24
KaKao 블라인드 테스트(하)  (0) 2019.01.19
for의 진행방식  (0) 2019.01.15
MFC :: 화면 캡쳐(capture.exe)  (0) 2018.12.23
Comments