본문 바로가기
C언어/C언어

[C언어]인클루드 가드의 뜻과 사용법(헤더가 꼬일 때,업계표준)

by Oliver_Candy 2023. 2. 15.

헤더파일(.h) 파일은 주료 함수선언과 전역변수 extern선언할 때 주로 들어간다. (물론 #define 같은 매크로도 들어간다.)

그리고 #include는 저번 글처럼 복사 붙여 넣기(확장)해주는 매크로이다.

 

헤더파일에 #define 같은 매크로를 다른 헤더파일에서도 사용을 해야 할 일이 있을 때, 양쪽 헤더 파일에 인클루드를 할 때가 있다.

예시코드 파일 3개를 보자

#include "b.h"

/* 코드 내용 생략 */

파일1 a.h

#include "a.h"

/* 코드 내용 생략 */

파일 2b.h

#include "a.h"

int main(void)
{
    /* 코드 내용 생략 */
    
    return 0;
}

파일 3 c.c

여기서 c.c 파일을 컴파일하게 되면 어떻게 될까?

 

 

 

 

  1. #include "a.h"에 의해서 a.h파일이 복붙 됨 
  2. a.h파일이 복붙 된 코드에서 #include "b.h"에 의해서 b.h파일이 복붙 됨
  3. b.h파일의 코드에서 #include "a.h"에 의해서 a.h파일이 복붙 됨
  4. 2~3 과정의 반복
  5. 반복되는 #include 복사롤 인한 오류 발생 즉, 헤더가 꼬이는 문제가 생김

#include 중첩이 너무 깊다는 오류

위와 같이 In file included from ./a.h:1: 과 In file included from ./b.h:1:가 계속 반복되다가 저절로 오류가 발생한다.

 

이와 같은 오류를 해결하는 방법이 2가지가 있는데 설명하겠다.

 

 해결책(1) : 인클루드가 중첩되는 상황 자체를 피한다

헤더파일에는 #include를 가능하면 넣지 말고. c파일에만 넣어서 인클루드가 중첩되는 상황을 피할 수 있다.

위와 같은 코드는 b헤더에 a헤더에 있는 함수들을 전방선언하는 방식으로 해결할 수 있다.

그렇지만 항상 이렇게 전방선언을 직접 하다 보면 코드를 수정할 때 하나하나 수정을 안 하기 위해서 헤더파일을 작성하는 것인데, 실수를 할 여지가 생기게 된다.

그렇기에 이 방식은 좋다고는 할 수가 없다.

 

 

 

 해결책(2) : 인클루드 가드(헤더가드)를 만든다

인클루드 가드란 인클루드를 할 때 헤더가 꼬이는 상황을 막기 위한 방식이다.

아까 전 코드를 인클루드 가드로 해서 만들어 보면

#ifndef A_H
#define A_H
#include "b.h"

/* 코드 내용 생략 */

#endif /* A_H */

파일 4 수정된 a.h

#ifndef B_H
#define B_H
#include "a.h"

/* 코드 내용 생략 */

#endif /* B_H */

파일 5 수정된 b.h

#include "a.h"

int main(void)
{
    /* 코드 내용 생략 */
    
    return 0;
}

파일 6 기존 c.c

이렇게 만들 수 있다. #ifndef라는 것은 매크로인데 '뒤에 있는 내용이 정의(#define) 되어있지 않은가?'를 나타내는 조건 매크로이다. 그래서 정의되어 있지 않다면 #endif 사이의 있는 내용을 복붙 해주게 된다.

이 방식을 차례대로 설명하자면

  1. #include "a.h"에 의해서 a.h파일이 복붙 됨
  2. a.h파일의 #ifndef A_H 즉, A_H가 정의된 적이 없으면 #endif 사이의 내용을 복붙 한다
  3. 그리고 다음 코드인 #define A_H로 A_H를 정의해 준다
  4. 다음 코드인 #include "b.h"로 b.h파일을 복붙 한다
  5. b.h파일의 #ifndef B_H 즉, B_H가 정의된 적이 없으면 #endif 사이의 내용을 복붙 한다
  6. 그리고 #define B_H로 B_H를 정의한다
  7. 그리고 다시 #include "a.h"를 불러온다
  8. a.h파일에서 #ifndef A_H에서 A_H가 정의되어 있으므로 #endif 사이의 코드는 지운다
  9. 인클루드 중첩 발생하지 않음

 

 

 

이 인클루드 가드를 통해서 헤더가 여러 번 인클루드 되는 것을 차단할 수 있다.

그리고 #define을 할 때 꼭 파일이름으로 해야 되는 건 아니지만 파일이름으로 해놓으면 가독성이 좋아서 어떤 파일에 인클루드 가드를 한지 알 수 있다.

그리고 #endif 뒤에도 주석을 넣는 이유도 마찬가지로 헤더파일의 인클루드 가드가 끝나는 위치를 쉽게 파악할 수 있기 때문에 넣어주자.

이는 포프선생님 피셜로 업계표준으로 쓰인다고 한다. 이런 방식을 고안해 낸 사람들이 진짜로 머리가 좋은 것 같다.

 

 

 

 

2023.01.09 - [POCU/COMP2200(C언어)] - [C]#include 의미 / 자료형 정리

 

[C언어]#include 의미 / 자료형 정리

#include 의미 1. 다른 파일에 구현된 함수나 변수를 사용할 수 있게 해준다. 2. #include 는 전처리기 지시문 중 하나 3. #include 는 컴파일 전에 텍스트를 복붙해주는 역할을 함 #include 가 작동되는 과정

olivertree-cs.tistory.com

 

출처 : POCU Academy COMP2200

댓글