Language/C

[C] C언어 컴파일 - 헤더 파일, 분할 컴파일, 조건부 컴파일

재은초 2026. 6. 9. 23:34
728x90
반응형

헤더 파일(header file)

  • C언어에서 함수는 사용되기 전에 먼저 해당 함수의 원형이 선언되어야 한다. 이 원칙은 표준 함수에도 그대로 적용되며, 표준 함수 또한 사용되기 전에 해당 함수의 원형이 선언되어야 한다.
  • 이러한 표준 함수의 원형 및 표준 함수와 관련된 다양한 정보를 가지고 있는 파일을 표준 헤더 파일이라고 한다.
  • 또한, 사용자는 자신만의 사용자 헤더 파일을 자유롭게 만들 수도 있다.
  • 헤더 파일의 확장자는 보통 .h를 사용하며, #include 선행처리 지시자를 사용하여 다른 파일에 포함시킬 수 있다.

표준 헤더 파일

  • 표준 함수의 원형 및 표준 함수와 관련된 다양한 정보를 가지고 있는 표준 헤더 파일은 그 크기가 상당히 크다. 하지만 크기가 큰 헤더 파일을 포함한다고 프로그램의 크기가 반드시 커지는 것은 아니다.
  • 헤더 파일의 내용은 실행 파일에 추가되는 내용보다는 컴파일러가 실행 파일을 만드는 데 사용하는 정보가 대부분이기 때문이다.
  • 표준 헤더 파일에 저장되는 정보는 다음과 같다.
    • 표준 함수의 원형
    • 표준 함수의 매크로 상수
    • 표준 함수의 사용자 정의 타입(구조체, 공용체) 정의
    • 매크로 함수의 정의

사용자 헤더 파일

  • 많은 개발자가 자신의 프로그램에 사용하기 위해서 자신만의 헤더 파일을 작성한다. 이러한 헤더 파일을 이용하면, 여러 파일에서 같이 공유하는 외부 변수를 선언할 수도 있다.
  • 다음 예제는 사용자가 직접 작성한 사용자 헤더 파일의 예제다.
#include <stdio.h>
#define COND 2   

struct book {
    char title[30];
    char author[30];
    int price;
};

void local(int);
int bigNum (int, int);

 

분할 컴파일

  • 작성된 모듈(module)은 개별적으로 컴파일된 후, 링커에 의해 하나의 실행 파일로 만들어진다. 이렇게 하나의 실행 파일을 만들기 위해서 소스 파일을 여러 개로 나누어 개발하는 방식을 분할 컴파일 방식이라고 한다.

https://www.tcpschool.com/c/c_complie_module

  • 최종적인 실행 파일의 생성을 위해서 접근하는 변수나 호출하는 함수가 어디에 있는지 서로 연결해주는 작업을 링크(link)라고 한다.

모듈(module)

  • 모듈(module)이란 프로그램을 구성하는 구성 요소로, 관련된 데이터와 함수를 하나로 묶은 단위를 의미한다.
  • 보통 하나의 소스 파일에 모든 함수를 작성하지 않고, 함수의 기능별로 따로 모듈을 구성한다. 이러한 모듈을 합쳐 하나의 파일로 작성하는 방식으로 프로그램을 만들게 된다.
  • 프로그램 코드를 기능별로 나눠서 독립된 파일에 저장하여 관리하는 방식을 모듈화 프로그래밍이라고 한다.

extern 키워드

  • 분할 컴파일 방식에서 여러 개의 소스 파일 사이의 상호 참조는 전역 변수와 전역 함수만이 가능하다.
  • 기본적으로 C 컴파일러는 프로그램에 등장하는 전역 변수를 오로지 해당 파일에서만 찾는다. 따라서 외부 파일에서 참조하는 전역 변수는 컴파일러에게 외부 파일에 존재하는 변수라는 사실을 따로 알려줘야 한다.
  • 외부 파일에서 선언된 전역 변수를 참조하기 위해서는 파일 내에서 extern 키워드를 사용해 다시 한 번 변수를 선언해야 한다. 그러면 C 컴파일러는 extern 키워드가 붙은 전역 변수가 외부 파일에 존재하는 변수임을 인식하고 컴파일을 진행하게 된다. extern 키워드가 붙은 전역 변수는 컴파일된 후, 링크 때가 돼서야 실제로 연결되게 된다.

static 키워드

  • 분할 컴파일 방식에서 변수의 접근 영역을 해당 파일로만 한정시키고자 할 때는 static 키워드를 사용하여 선언하면 된다. 이렇게 선언된 변수는 다른 소스 파일에서 extern 키워드를 사용해 선언하더라도 접근할 수 없는 전역 변수가 된다.
  • 다음 그림은 extern 키워드로 선언된 변수와 static 키워드로 선언된 변수에 접근할 수 있는 영역을 보여준다.

https://www.tcpschool.com/c/c_complie_module

 

조건부 컴파일(conditional compile)

  • 조건부 컴파일을 사용하면 지정한 조건에 따라 코드의 일정 부분을 컴파일할지 안 할지를 지정할 수 있다.
  • 이러한 조건부 컴파일에 사용할 수 있는 조건부 컴파일 지시자(conditional compile directive)는 ① #if ② #ifdef ③ #ifndef가 있다.

#if

  • #if 지시자를 이용한 조건부 컴파일의 사용법은 C언어의 if 조건문과 매우 비슷하다.
#if 조건식1
    컴파일할 명령문1

#elif 조건식2
    컴파일할 명령문2

#else
    컴파일할 명령문3

#endif
  • #if 지시자 다음에 나오는 조건식1의 결과가 0이 아니면 참, 0이면 거짓으로 간주한다.
  • #elif 지시자를 사용하여 조건식을 여러 개 사용할 수도 있다.
  • #else 지시자를 사용하여 모든 조건에 해당하지 않는 경우를 지정할 수도 있다.
  • 하지만 C언어의 조건문과는 달리 #endif 지시자를 사용하여 반드시 조건부 컴파일의 끝을 명시해야 한다.

#ifdef

  • 여러 개의 헤더 파일을 작성한 후에 전부 합치다 보면, 같은 이름의 변수나 함수가 중복으로 선언되어 있을 가능성이 있다. 이러한 경우에는 #ifdef 지시자를 사용하여 중복 선언의 가능성을 없앨 수 있다.
#ifdef 매크로이름
    컴파일할 명령문1

#elif 조건식
    컴파일할 명령문2

#else
    컴파일할 명령문3

#endif
  • #ifdef는 'if defined'라는 문장을 줄여서 만든 것으로  #ifdef 지시자 다음에 나오는 매크로 이름과 같은 이름의 매크로가 이미 정의되어 있으면, 컴파일할 명령문1이 컴파일될 것이다.
  • 만약 매크로 이름과 같은 이름의 매크로가 정의되어 있지 않으면, 컴파일할 명령문1은 컴파일되지 않고 넘어갈 것이다.
  • 또한 #elif 지시자와 #else 지시자를 사용하여 컴파일의 조건을 확장할 수도 있다.
#include <stdio.h>
#define PI 3.14 // 이 부분을 주석처리하고 난 후에 다시 실행시켜 보세요!  

int main(void) {
    #ifdef PI
        printf("매크로 상수 PI가 선언되어 있으며 그 값은 %.2f입니다.\n", PI);

    #else
        puts("매크로 상수 PI가 선언되어 있지 않습니다.");

    #endif
    
    return 0;
}

// 매크로 상수 PI가 선언되어 있으며 그 값은 3.14입니다.

#ifndef

  • #ifndef 지시자를 이용한 조건부 컴파일의 사용법은 #ifdef 지시자를 이용한 조건부 컴파일과 거의 같다. 다만 #ifndef 지시자는 #ifdef 지시자와는 정반대의 조건을 검사하게 된다.
#ifndef 매크로이름
    컴파일할 명령문1

#elif 조건식
    컴파일할 명령문2

#else
    컴파일할 명령문3

#endif
  • #ifndef는 'if not defined'라는 문장을 줄여서 만든 것으로 #ifndef 지시자 다음에 나오는 매크로 이름과 같은 이름의 매크로가 앞서 정의되어 있지 않으면, 컴파일할 명령문1이 컴파일될 것이다.
  • 만약 매크로 이름과 같은 이름의 매크로가 앞서 정의되어 있으면, 컴파일할 명령문1은 컴파일되지 않고 넘어갈 것이다.
  • 또한 #elif 지시자와 #else 지시자를 사용하여 컴파일의 조건을 확장할 수도 있다.
#include <stdio.h> //#define PI 3.14 // 이 부분의 주석처리를 없애고 난 후에 다시 실행시켜 보세요!  

int main(void) {
    #ifndef PI
        puts("매크로 상수 PI가 선언되어 있지 않습니다.");

    #else
        printf("매크로 상수 PI가 선언되어 있으며 그 값은 %.2f입니다.\n", PI);

    #endif

    return 0;
}  

// 매크로 상수 PI가 선언되어 있지 않습니다.
  • 사용자 헤더 파일을 선언할 때에는 중복 선언을 피하기 위해 파일 내의 모든 내용을 #ifdef나 #ifndef, #endif 지시자로 감싸는 것이 좋다.

 

Reference

728x90
반응형