본문 바로가기

IT/C|C++

[C] #ifndef을 이용한 header 중복 방지

이번 포스팅에서는 전처리문 #ifndef을 이용하여 header파일의 중복을 막는 방법을 포스팅하겠다.


먼저 #ifndef이 적용된 예제파일을 먼저 보겠다.


_ #ifndef을 이용한 예제


1. coordinate.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#ifndef COORDINATE
#define COORDINATE
 
#include <stdio.h>
 
struct coordinate{
    int x;
    int y;
};
 
void print_coordinate(struct coordinate *coord);
 
#endif
 
cs


2. coordinate.c

1
2
3
4
5
6
7
#include "coordinate.h"
 
void print_coordinate(struct coordinate *coord){
    printf("X: %d\n", coord->x);
    printf("Y: %d\n", coord->y);
}
 
cs


3. main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
 
#include "coordinate.h"
 
int main(void){
    struct coordinate coord;
 
    coord.x = 5;
    coord.y = 3;
 
    print_coordinate(&coord);
 
    return 0;
}
 
cs


4. Makefile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 
VPATH=./
EXEC=main
OBJDIR=./
 
CC=gcc
 
CFLAGS=-Wall -Wfatal-errors
 
OBJ=coordinate.o main.o
 
OBJS = $(addprefix $(OBJDIR), $(OBJ))
DEPS = $(wildcard ./*.h) Makefile
 
all: obj results $(EXEC)
 
$(EXEC): $(OBJS)
    $(CC) $(COMMON) $(CFLAGS) $^ -o $@ $(LDFLAGS)
 
$(OBJDIR)%.o: %.c $(DEPS)
    $(CC) $(COMMON) $(CFLAGS) -c $< -o $@
 
obj:
    mkdir -p obj
results:
    mkdir -p results
 
.PHONY: clean
 
clean:
    rm -rf $(OBJS) $(EXEC)
 
cs



해당 코드는, coordinate라는 구조체를 선언하고, 이를 출력해주는 함수를 coordinate.h, coordinate.c에 넣어놓고, 이를 main.c에서 참조해서 사용하는 프로그램이다.


Makefile을 이용해서 make에서 프로그램을 실행시켜보면 다음과 같은 결과를 출력한다.




예제가 잘 작동하는 것을 확인했다.


이제 왜 #ifndef이라는 전처리문을 사용하는지 다음 예제를 이용해서 확인해보자.


_ #ifndef이 없는 예제


1. coordinate.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//#ifndef COORDINATE
//#define COORDINATE
 
#include <stdio.h>
 
struct coordinate{
    int x;
    int y;
};
 
void print_coordinate(struct coordinate *coord);
 
//#endif
 
cs


2. coordinate.c

1
2
3
4
5
6
7
#include "coordinate.h"
 
void print_coordinate(struct coordinate *coord){
    printf("X: %d\n", coord->x);
    printf("Y: %d\n", coord->y);
}
 
cs


3. main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
 
#include "coordinate.h"
#include "coordinate.h"
 
int main(void){
    struct coordinate coord;
 
    coord.x = 5;
    coord.y = 3;
 
    print_coordinate(&coord);
 
    return 0;
}
 
cs


4. Makefile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 
VPATH=./
EXEC=main
OBJDIR=./
 
CC=gcc
 
CFLAGS=-Wall -Wfatal-errors
 
OBJ=coordinate.o main.o
 
OBJS = $(addprefix $(OBJDIR), $(OBJ))
DEPS = $(wildcard ./*.h) Makefile
 
all: obj results $(EXEC)
 
$(EXEC): $(OBJS)
    $(CC) $(COMMON) $(CFLAGS) $^ -o $@ $(LDFLAGS)
 
$(OBJDIR)%.o: %.c $(DEPS)
    $(CC) $(COMMON) $(CFLAGS) -c $< -o $@
 
obj:
    mkdir -p obj
results:
    mkdir -p results
 
.PHONY: clean
 
clean:
    rm -rf $(OBJS) $(EXEC)
 
cs



해당 코드는 첫번째 예제와는 다르게 #ifndef을 주석처리하고, main.c에서 coordinate.h를 두번 넣은 것을 제외하고는 같은 파일이다.

해당 코드를 make해서 결과를 확인하면 다음과 같다.




다음과 같이 coordinate.h:6:8 error: redefinition of 'struct coordinate'라는 에러를 출력한다.

해당 구조체가 재 선언되었다고 이야기하고있다.


해당 코드와 같은 작은 프로그램의 경우야 이를 확인하는게 크게 어렵지 않지만, 


대규모 프로그램에서 다음과 같이 헤더파일의 중복 선언은 정말 찾기가 너무 힘들다. 


따라서 #ifndef같은 전처리 문을 사용해서 중복 선언을 막게된다.


1
2
3
4
5
6
7
#ifndef STRING
#define STRING
 
(...)
 
#endif
 
cs


다음과 같이 #ifndef을 사용하게 되면, 코드의 흐름은 다음과 같다.


  • STRING이라는 상수가 선언되어있는지 확인한다.
  • 상수가 선언이 안되있다면, STRING이라는 상수를 선언한다.
  • header에 들어갈 내용이 작성된다.
  • 만약에 STRING이라는 상수가 선언이 안되있다면, 그냥 해당 참조는 무시하게 된다.


이런 형태를 만들어서 중복 참조를 막는게 header파일에서 #ifndef이라는 전처리문을 사용하는 핵심 이유가 된다.


그렇다면, 전처리문을 사용해보고 헤더파일을 중복참조해보자.


해당코드는 이미 제공되었기 때문에, 코드와 결과는 생략하도록 하겠다.



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

[C] 외부 변수 참조, extern  (0) 2017.05.01
[C] 구조체, Structure  (0) 2017.04.24
[C] 재귀 함수 Recursion function  (0) 2017.03.28
[MinGW/Eclipse c++] Compile Error  (0) 2016.06.06
[Eclipse C++]Install Eclipse c++/ Eclipse c++ 설치하기  (0) 2016.06.06