본문 바로가기
C언어

C언어 컴파일

by FraisGout 2020. 7. 5.

헤더 파일(header file)

C언어에서 함수는 사용되기 전에 먼저 해당 함수의 원형이 선언되어야 합니다.

 

이 원칙은 표준 함수에도 그대로 적용되며, 표준 함수 또한 사용되기 전에 해당 함수의 원형이 선언되어야 합니다.

 

 

 

이러한 표준 함수의 원형 및 표준 함수와 관련된 다양한 정보를 가지고 있는 파일을 표준 헤더 파일이라고 합니다.

 

또한, 사용자는 자신만의 사용자 헤더 파일을 자유롭게 만들 수도 있습니다.

 

헤더 파일의 확장자는 보통 .h를 사용하며, #include 선행처리 지시자를 사용하여 다른 파일에 포함시킬 수 있습니다.

 

표준 헤더 파일

표준 함수의 원형 및 표준 함수와 관련된 다양한 정보를 가지고 있는 표준 헤더 파일은 그 크기가 상당히 큽니다.

 

하지만 크기가 큰 헤더 파일을 포함한다고 프로그램의 크기가 반드시 커지는 것은 아닙니다.

 

헤더 파일의 내용은 실행 파일에 추가되는 내용보다는 컴파일러가 실행 파일을 만드는 데 사용하는 정보가 대부분이기 때문입니다.

 

 

 

표준 헤더 파일에 저장되는 정보는 다음과 같습니다.

 

 

 

1. 표준 함수의 원형

 

2. 표준 함수의 매크로 상수

 

3. 표준 함수의 사용자 정의 타입(구조체, 공용체) 정의

 

4. 매크로 함수의 정의

 

사용자 헤더 파일

많은 개발자가 자신의 프로그램에 사용하기 위해서 자신만의 헤더 파일을 작성합니다.

 

이러한 헤더 파일을 이용하면, 여러 파일에서 같이 공유하는 외부 변수를 선언할 수도 있습니다.

 

 

 

다음 예제는 사용자가 직접 작성한 사용자 헤더 파일의 예제입니다.

 

예제

#include <stdio.h>

 

#define COND 2

 

 

 

struct book

 

{

 

char title[30];

 

char author[30];

 

int price;

 

};

 

 

 

void local(int);

 

int bigNum (int, int);

 

모듈(module)

모듈(module)이란 프로그램을 구성하는 구성 요소로, 관련된 데이터와 함수를 하나로 묶은 단위를 의미합니다.

 

보통 하나의 소스 파일에 모든 함수를 작성하지 않고, 함수의 기능별로 따로 모듈을 구성합니다.

 

이러한 모듈을 합쳐 하나의 파일로 작성하는 방식으로 프로그램을 만들게 됩니다.

 

위처럼 프로그램 코드를 기능별로 나눠서 독립된 파일에 저장하여 관리하는 방식을 모듈화 프로그래밍이라고 합니다.

 

분할 컴파일

작성된 모듈(module)은 개별적으로 컴파일된 후, 링커에 의해 하나의 실행 파일로 만들어집니다.

 

이렇게 하나의 실행 파일을 만들기 위해서 소스 파일을 여러 개로 나누어 개발하는 방식을 분할 컴파일 방식이라고 합니다.

 

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

 

extern 키워드

분할 컴파일 방식에서 여러 개의 소스 파일 사이의 상호 참조는 전역 변수와 전역 함수만이 가능합니다.

 

기본적으로 C 컴파일러는 프로그램에 등장하는 전역 변수를 오로지 해당 파일에서만 찾습니다.

 

따라서 외부 파일에서 참조하는 전역 변수는 컴파일러에게 외부 파일에 존재하는 변수라는 사실을 따로 알려줘야 합니다.

 

 

 

외부 파일에서 선언된 전역 변수를 참조하기 위해서는 파일 내에서 extern 키워드를 사용해 다시 한 번 변수를 선언해야 합니다.

 

그러면 C 컴파일러는 extern 키워드가 붙은 전역 변수가 외부 파일에 존재하는 변수임을 인식하고 컴파일을 진행하게 됩니다.

 

extern 키워드가 붙은 전역 변수는 컴파일된 후, 링크 때가 돼서야 실제로 연결되게 됩니다.

 

static 키워드

분할 컴파일 방식에서 변수의 접근 영역을 해당 파일로만 한정시키고자 할 때는 static 키워드를 사용하여 선언하면 됩니다.

 

이렇게 선언된 변수는 다른 소스 파일에서 extern 키워드를 사용해 선언하더라도 접근할 수 없는 전역 변수가 됩니다.

 

 

조건부 컴파일(conditional compile)

조건부 컴파일을 사용하면 지정한 조건에 따라 코드의 일정 부분을 컴파일할지 안 할지를 지정할 수 있습니다.

 

이러한 조건부 컴파일에 사용할 수 있는 조건부 컴파일 지시자(conditional compile directive)는 다음과 같습니다.

 

 

 

1. #if

 

2. #ifdef

 

3. #ifndef

 

#if

#if 지시자를 이용한 조건부 컴파일의 사용법은 C언어의 if 조건문과 매우 비슷합니다.

 

 

 

#if 지시자를 이용한 조건부 컴파일의 형식은 다음과 같습니다.

 

형식

#if 조건식1

 

컴파일할 명령문1

 

#elif 조건식2

 

컴파일할 명령문2

 

#else

 

컴파일할 명령문3

 

#endif

 

 

 

 

 

#if 지시자 다음에 나오는 조건식1의 결과가 0이 아니면 참, 0이면 거짓으로 간주합니다.

 

또한, #elif 지시자를 사용하여 조건식을 여러 개 사용할 수도 있습니다.

 

#else 지시자를 사용하여 모든 조건에 해당하지 않는 경우를 지정할 수도 있습니다.

 

하지만 C언어의 조건문과는 달리 #endif 지시자를 사용하여 반드시 조건부 컴파일의 끝을 명시해야 합니다.

 

 

예제

#include <stdio.h>

 

#define COND 2

 

 

 

int main(void)

 

{

 

#if COND == 1

 

puts("매크로 상수 COND가 선언되어 있으며 그 값은 1입니다.");

 

#elif COND == 2

 

puts("매크로 상수 COND가 선언되어 있으며 그 값은 2입니다.");

 

#elif COND == 3

 

puts("매크로 상수 COND가 선언되어 있으며 그 값은 3입니다.");

 

#endif

 

return 0;

 

}

 

위의 예제는 단지 조건부 컴파일 지시자의 개념을 설명하기 위해 만든 예제입니다.

 

실제로는 위와 같이 조건부 컴파일 지시자를 조건문처럼 사용하지는 않습니다.

 

#ifdef

여러 개의 헤더 파일을 작성한 후에 전부 합치다 보면, 같은 이름의 변수나 함수가 중복으로 선언되어 있을 가능성이 있습니다.

 

이러한 경우에는 #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;

 

}

 

 

#ifndef

#ifndef 지시자를 이용한 조건부 컴파일의 사용법은 #ifdef 지시자를 이용한 조건부 컴파일과 거의 같습니다.

 

다만 #ifndef 지시자는 #ifdef 지시자와는 정반대의 조건을 검사하게 됩니다.

 

 

 

#ifndef 지시자를 이용한 조건부 컴파일의 형식은 다음과 같습니다.

 

형식

#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;

 

}

 

사용자 헤더 파일을 선언할 때에는 중복 선언을 피하기 위해 파일 내의 모든 내용을 #ifdef#ifndef, #endif 지시자로 감싸는 것이 좋습니다.

'C언어' 카테고리의 다른 글

C언어 참조  (0) 2020.07.05
C언어 선행처리  (0) 2020.07.05
C언어 입력 & 출력  (0) 2020.07.05
C언어 구조체  (0) 2020.07.05
C언어 문자  (0) 2020.07.05

댓글