[C/C++] Declaration VS Definition, header의 역할

YumeIroVillain·2022년 7월 31일
0

개발노트

목록 보기
17/28

2.7장~2.13장까지의 정독이 큰 도움이 된다

Declaration(선언)

  • Compile 하기 위해 필요한 모든 것
  • Existence만 알려주고, 구체적인 멤버변수, 메소드, size 등은 Definition을 통해서만 확인가능
  • 그럼에도 불구하고 Compile 가능한 이유는, 아래 form 을 따르기 때문

이해 돕는 예

아래 코드가 있다 치자.

#include <iostream>

int add(int x, int y); // forward declaration of add() using function prototype

int main()
{
    int tmp = add(3,4);
    return 0;
}

// note: No definition for function add

뭔 이상한 코드가 다 있나 할 것이다.
prototype declaration 만 있을 뿐, add함수의 body는 어디에도 선언되어있지 않다.
컴파일될까?

된다!
심지어 7번줄의 add 호출문도 어셈블리 7번줄처럼 add 심볼을 찾아 branch 뛰라고 적혀있다.
다만, add 심볼은 정작 어셈블리 어디에도 적혀있지 않다.
그것은, compile 의 역할은 딱 "각 file을 independently 하게 asm(.o)으로 바꾸고, .o에 숨어있는 심볼들 짜맞추기는 링커가 전담한다"로 링커와 컴파일러가 분업되어있기 때문이다.
즉, 위 코드는 컴파일이 된다. 그러나 링크가 안된다.

여기서 두 가지 사실을 알 수 있다.
1. Declaration은 한 program 내에서 여러 번 선언가능. 한 file 내에서는 여러 번 불가능.
2. Definition은 한 program 내에서 단 1번 선언가능.

따라서, 자연스럽게 코더는 이렇게 프로그램을 짜게 된다.
1. Declaration은 .h에 단 한 번 작성.
2. Definition은 .cpp에 단 한 번 작성.
3. .cpp가 필요한 경우, .h를 #include 한다. 이 때, Declaration은 program 전체에는 여러번 등장해도 되므로 문제가 발생하지 않는다.
주의: .h는 여러 cpp에서 끌어쓸 수 있다.
따라서, .h 안에 구체적인 Definition 이 포함된다면, 99%의 확률로 링크 에러가 발생한다.
따라서, .h에는 순수하게 "Declaration" 만 포함토록 하자.

Definition(정의)

Declaration의 반대이다.
멤버변수, size까지 상세히 기술된 것이다.

선언과 달리, Definition은 한 file 내에 중복시 compile error, 한 program 내 중복시 linker error 를 낸다.
즉 중복선언 안된다.


변수의 Declaration VS Definition

함수는

int foo(int a);

하면 Declaration으로 취급된다.
즉,

#include <iostream>

int add(int x, int y); // forward declaration of add() using function prototype
int add(int x, int y); // forward declaration of add() using function prototype

int main()
{
    int tmp = add(3,4);
    return 0;
}

// note: No definition for function add
         

해도 컴파일 된다.
ODR을 어기지 않았기 때문이다.(Declaration != Definition)

반면에 함수와 달리, 변수는

int a;

하면 Definition으로 취급된다.
이것이

int main(){
	int a; // DEFINITION
    int a; // DEFINITION TWICE -> THUS ERROR!
	return 0;
}

에서 에러가 발생하는 이유이다. One Definition Rule(이하 ODR)을 어기기 때문이다.
단, extern 으로 선언된 변수는

extern int a;

해도 Declaration으로 취급된다.


헤더파일의 Technique

  • .h를 통한 Forward Declaration 을 사용하여, Circular Dependencies 를 깰 수 있다.
profile
HW SW 둘다 공부하는 혼종의 넋두리 블로그 / SKKU SSE 17 / SWM 11th

0개의 댓글