|
| 1 | +# #define 가드 |
| 2 | + |
| 3 | +모든 헤더 파일은 다중 포함을 방지하기 위해 `#define` 가드를 가져야 합니다. 심볼 이름의 형식은 `<PROJECT>_<PATH>_<FILE>_H_`이어야 합니다. |
| 4 | + |
| 5 | +고유성을 보장하기 위해 프로젝트의 소스 트리에서 전체 경로를 기반으로 해야 합니다. 예를 들어, 프로젝트 `foo`의 `foo/src/bar/baz.h` 파일은 다음과 같은 가드를 가져야 합니다: |
| 6 | + |
| 7 | +```cpp |
| 8 | +#ifndef FOO_BAR_BAZ_H_ |
| 9 | +#define FOO_BAR_BAZ_H_ |
| 10 | + |
| 11 | +... |
| 12 | + |
| 13 | +#endif // FOO_BAR_BAZ_H_ |
| 14 | +``` |
| 15 | + |
| 16 | +--- |
| 17 | + |
| 18 | +## 이해하기 쉽게 설명하기 |
| 19 | + |
| 20 | +### #define 가드란? |
| 21 | + |
| 22 | +`#define` 가드(또는 헤더 가드, header guard)는 헤더 파일이 여러 번 포함되는 것을 방지하는 메커니즘입니다. 같은 헤더 파일이 여러 번 `#include`되면 중복 정의 오류가 발생할 수 있는데, 가드를 사용하면 이를 방지할 수 있습니다. |
| 23 | + |
| 24 | +### 왜 필요한가? |
| 25 | + |
| 26 | +헤더 파일이 여러 번 포함될 수 있는 상황: |
| 27 | + |
| 28 | +- 여러 소스 파일에서 같은 헤더를 포함하는 경우 |
| 29 | +- 헤더 파일이 다른 헤더 파일을 포함하고, 그 헤더가 또 다른 헤더를 포함하는 경우 |
| 30 | +- 복잡한 의존 관계로 인해 간접적으로 같은 헤더가 여러 번 포함되는 경우 |
| 31 | + |
| 32 | +가드가 없으면 다음과 같은 오류가 발생할 수 있습니다: |
| 33 | + |
| 34 | +```cpp |
| 35 | +// widget.h |
| 36 | +class Widget { ... }; // 첫 번째 포함 시 정의됨 |
| 37 | +// ... 나중에 다시 포함되면 |
| 38 | +class Widget { ... }; // 중복 정의 오류! |
| 39 | +``` |
| 40 | +
|
| 41 | +### 가드 이름 규칙 |
| 42 | +
|
| 43 | +가드 심볼 이름은 다음 형식을 따라야 합니다: |
| 44 | +
|
| 45 | +```text |
| 46 | +<PROJECT>_<PATH>_<FILE>_H_ |
| 47 | +``` |
| 48 | + |
| 49 | +- `<PROJECT>`: 프로젝트 이름 (대문자) |
| 50 | +- `<PATH>`: 소스 트리 내 경로 (슬래시 `/`를 언더스코어 `_`로 변환) |
| 51 | +- `<FILE>`: 파일 이름 (확장자 제외, 대문자) |
| 52 | +- 끝에 `_H_` 추가 |
| 53 | + |
| 54 | +**중요**: `src`, `include`, `lib` 같은 일반적인 디렉토리 이름은 경로에서 **제외**합니다. 이는 다음과 같은 이유 때문입니다: |
| 55 | + |
| 56 | +- **안정성**: 프로젝트 구조가 변경되어 `src`를 다른 이름으로 바꾸거나 제거해도 가드 이름이 변경되지 않습니다. |
| 57 | +- **명확성**: `src`나 `include`는 많은 프로젝트에서 사용하는 일반적인 디렉토리 이름이라 의미 있는 정보를 제공하지 않습니다. |
| 58 | +- **간결성**: 실제 의미 있는 경로 정보만 포함하여 가드 이름을 더 간결하게 만듭니다. |
| 59 | + |
| 60 | +예를 들어: |
| 61 | + |
| 62 | +- `foo/src/bar/baz.h` → `FOO_BAR_BAZ_H_` (src 제외) |
| 63 | +- `myproject/include/utils/helper.h` → `MYPROJECT_UTILS_HELPER_H_` (include 제외) |
| 64 | + |
| 65 | +### 예시 |
| 66 | + |
| 67 | +프로젝트 구조와 가드 이름 예시: |
| 68 | + |
| 69 | +```text |
| 70 | +프로젝트: MyProject |
| 71 | +파일 경로: myproject/src/ui/widget.h |
| 72 | +가드 이름: MYPROJECT_UI_WIDGET_H_ |
| 73 | +``` |
| 74 | + |
| 75 | +```cpp |
| 76 | +// myproject/src/ui/widget.h |
| 77 | +#ifndef MYPROJECT_UI_WIDGET_H_ |
| 78 | +#define MYPROJECT_UI_WIDGET_H_ |
| 79 | + |
| 80 | +class Widget { |
| 81 | + // ... |
| 82 | +}; |
| 83 | + |
| 84 | +#endif // MYPROJECT_UI_WIDGET_H_ |
| 85 | +``` |
| 86 | + |
| 87 | +다른 예시: |
| 88 | + |
| 89 | +```text |
| 90 | +프로젝트: MyProject |
| 91 | +파일 경로: myproject/include/utils/string_utils.h |
| 92 | +가드 이름: MYPROJECT_UTILS_STRING_UTILS_H_ |
| 93 | +``` |
| 94 | + |
| 95 | +```cpp |
| 96 | +// myproject/include/utils/string_utils.h |
| 97 | +#ifndef MYPROJECT_UTILS_STRING_UTILS_H_ |
| 98 | +#define MYPROJECT_UTILS_STRING_UTILS_H_ |
| 99 | + |
| 100 | +// ... |
| 101 | + |
| 102 | +#endif // MYPROJECT_UTILS_STRING_UTILS_H_ |
| 103 | +``` |
| 104 | + |
| 105 | +### 가드 작성 방법 |
| 106 | + |
| 107 | +1. **파일 시작 부분**: `#ifndef`와 `#define`을 파일의 맨 위에 작성 |
| 108 | +2. **파일 끝 부분**: `#endif`를 파일의 맨 끝에 작성하고 주석으로 가드 이름 표시 |
| 109 | + |
| 110 | +```cpp |
| 111 | +#ifndef PROJECT_PATH_FILE_H_ |
| 112 | +#define PROJECT_PATH_FILE_H_ |
| 113 | + |
| 114 | +// 헤더 파일 내용 |
| 115 | + |
| 116 | +#endif // PROJECT_PATH_FILE_H_ |
| 117 | +``` |
| 118 | + |
| 119 | +### 주의사항 |
| 120 | + |
| 121 | +- 가드 이름은 **반드시 고유**해야 합니다. 프로젝트 전체에서 중복되지 않아야 합니다. |
| 122 | +- 전체 경로를 기반으로 하면 파일이 이동되어도 고유성이 보장됩니다. |
| 123 | +- 가드 이름 끝의 주석(`// PROJECT_PATH_FILE_H_`)은 가독성을 위해 권장됩니다. |
0 commit comments