콘텐츠로 이동

#define 가드

모든 헤더 파일은 다중 포함을 방지하기 위해 #define 가드를 가져야 합니다. 심볼 이름의 형식은 <PROJECT>_<PATH>_<FILE>_H_이어야 합니다.

고유성을 보장하기 위해 프로젝트의 소스 트리에서 전체 경로를 기반으로 해야 합니다. 예를 들어, 프로젝트 foofoo/src/bar/baz.h 파일은 다음과 같은 가드를 가져야 합니다:

#ifndef FOO_BAR_BAZ_H_
#define FOO_BAR_BAZ_H_

...

#endif  // FOO_BAR_BAZ_H_

이해하기 쉽게 설명하기

#define 가드란?

#define 가드(또는 헤더 가드, header guard)는 헤더 파일이 여러 번 포함되는 것을 방지하는 메커니즘입니다. 같은 헤더 파일이 여러 번 #include되면 중복 정의 오류가 발생할 수 있는데, 가드를 사용하면 이를 방지할 수 있습니다.

왜 필요한가?

헤더 파일이 여러 번 포함될 수 있는 상황:

  • 여러 소스 파일에서 같은 헤더를 포함하는 경우
  • 헤더 파일이 다른 헤더 파일을 포함하고, 그 헤더가 또 다른 헤더를 포함하는 경우
  • 복잡한 의존 관계로 인해 간접적으로 같은 헤더가 여러 번 포함되는 경우

가드가 없으면 다음과 같은 오류가 발생할 수 있습니다:

// widget.h
class Widget { ... };  // 첫 번째 포함 시 정의됨
// ... 나중에 다시 포함되면
class Widget { ... };  // 중복 정의 오류!

가드 이름 규칙

가드 심볼 이름은 다음 형식을 따라야 합니다:

<PROJECT>_<PATH>_<FILE>_H_
  • <PROJECT>: 프로젝트 이름 (대문자)
  • <PATH>: 소스 트리 내 경로 (슬래시 /를 언더스코어 _로 변환)
  • <FILE>: 파일 이름 (확장자 제외, 대문자)
  • 끝에 _H_ 추가

여기서 <PATH>#include에 사용하는 경로와 같은 경로, 즉 프로젝트 소스 트리의 루트를 기준으로 한 상대 경로입니다. 따라서 핵심은 "특정 디렉토리 이름을 제외한다"가 아니라, 포함 경로를 그대로 대문자로 바꾸고 슬래시를 _로 치환한 뒤 _H_를 붙인다는 것입니다.

예를 들어 프로젝트 foo의 파일 foo/src/bar/baz.h는 가드가 FOO_BAR_BAZ_H_가 됩니다. src가 이 프로젝트의 소스 루트이므로 트리 내 경로는 bar/baz.h이고(이 파일은 #include "bar/baz.h"로 포함됩니다), 여기에 프로젝트 이름 foo를 앞에 붙인 것입니다. 이는 "포함 순서와 이름" 규칙에서 google-awesome-project/src/base/logging.h#include "base/logging.h"로 포함하는 것과 같은 원리입니다.

즉, 소스 루트가 srcinclude든 그 아래의 경로만 가드에 반영되며, 경로가 다르면 가드도 달라져 고유성이 보장됩니다.

예시

프로젝트 구조와 가드 이름 예시:

프로젝트: MyProject
파일 경로: myproject/src/ui/widget.h
가드 이름: MYPROJECT_UI_WIDGET_H_
// myproject/src/ui/widget.h
#ifndef MYPROJECT_UI_WIDGET_H_
#define MYPROJECT_UI_WIDGET_H_

class Widget {
  // ...
};

#endif  // MYPROJECT_UI_WIDGET_H_

다른 예시:

프로젝트: MyProject
파일 경로: myproject/include/utils/string_utils.h
가드 이름: MYPROJECT_UTILS_STRING_UTILS_H_
// myproject/include/utils/string_utils.h
#ifndef MYPROJECT_UTILS_STRING_UTILS_H_
#define MYPROJECT_UTILS_STRING_UTILS_H_

// ...

#endif  // MYPROJECT_UTILS_STRING_UTILS_H_

가드 작성 방법

  1. 파일 시작 부분: #ifndef#define을 파일의 맨 위에 작성
  2. 파일 끝 부분: #endif를 파일의 맨 끝에 작성하고 주석으로 가드 이름 표시
#ifndef PROJECT_PATH_FILE_H_
#define PROJECT_PATH_FILE_H_

// 헤더 파일 내용

#endif  // PROJECT_PATH_FILE_H_

주의사항

  • 가드 이름은 반드시 고유해야 합니다. 프로젝트 전체에서 중복되지 않아야 합니다.
  • 전체 경로를 기반으로 하면 파일이 이동되어도 고유성이 보장됩니다.
  • 가드 이름 끝의 주석(// PROJECT_PATH_FILE_H_)은 가독성을 위해 권장됩니다.