본문 바로가기
프로그래밍/C & C++

<C> 기본예제 Day03 - 함수와 분할 컴파일

by 리나그(ReenAG) 2021. 3. 2.
728x90
반응형

이번 시간에 복습할 것은 2가지이다. 첫째로, 기본적으로 C 언어에대한 개념 설명을 하려고 한다. 지루한 파트이겠지만, 프로그래머라면 상식이니까 어느정도는 숙지하자. 둘째로, 다양한 함수와 기능을 테스트 하기 위해서 분할 컴파일이라는 것을 배우고, include의 진정한 의미를 알아보도록 하겠다.

 

그럼, C언어란 무언지를 알기위해서, 헤더 파일이라는 것을 하나 작성해보도록 하겠다. 너무 걱정할필요 없이, Day04.c와 함께, Day04.h라는 이름의 파일을 1개 작성하면 된다. 만약 [New] -> [header file]을 통해서 만들어 두었으면, 빈 파일이 아니라 무언가 이상한 것이 적혀있는 파일이 완성된다.

 

<Day04.h>

/*
 * Day04.h 
 * 
 * Created on: 2020. 12. 18. 
 * Author: OkRetry */ 
 
 #ifndef SRC_DAY04_H_ 
 #define SRC_DAY04_H_ 
 
 
 
 #endif /* SRC_DAY04_H_ */

 

뭔가 전에 작성한 예제 코드와는 전혀 다른 느낌의 코드라서 당황했을 지도 모르겠다. 하나하나 알아가 보자.

 

바로 주석이 무엇인지에 대한 설명부터 하겠다..... 라고 하면 좋겠지만, 그전에, "컴파일러"라는 개념을 설명하겠다. 걱정말라. 상당히 단순하게 설명할 수 있다. 저번에 예제 코드를 실행하면서 우선 망치 같이 생긴 [Build]버튼을 눌러 빌드를 한 뒤, [Launch]라는 버튼을 눌러 실행을 했을 것이다. 눈치가 빠른 학생들은 [Build]버튼이 눌리면 .exe파일을 만들고, [Launch]버튼이 눌리면 그 .exe를 실행시키는 것임을 알아냈을 것이다. 그렇다면 그 [Build]가 어떻게 .exe를 만드는지 생각해 보았는가?

 

그것은 "컴파일"이라는 과정을 거치기 때문이다. 컴퓨터는 Day04.c같은 소스파일만 가지고 있어서 아무것도 하지 못한다. Windows에서는 .exe, 끽해야 .msi의 확장자가 아니고서야, 파일을 실행할 수 없다. 그렇기에, 여기서 "컴파일러"라는 것이 등장한다. 컴파일러는 여러분이 작성한 코드를 보고 컴퓨터가 알아들을 수 있는 언어인 .exe로 바꾸어 준다. 그게 컴파일러의 주요한 역할이다. 위의 내용을 요약하자면 아래의 그림과 같다.

프로그램이 어떻게 실행되는지에 대한 간단한 모식도

그렇다면 어째서 컴퓨터는 어째서 .c확장자를 가진 소스파일을 실행시키지 못하냐고 물을 수 있다. 왜냐하면, 컴퓨터는 본질적으로, "상당히 끔찍하게" 멍청하기 때문이다. "아니 멍청하다니, 본인도 지금 컴퓨터에 글을 쓰고 있구만, 이거 무슨 소리야?"라고 생각하시는 분들도 있을지 모르겠다. 그것은, 여러분들이 쓰고 있는 모든 기계(하드웨어) 위에 인간의 지혜로 자아낸 소프트웨어라는 것이 동작하고 있는 것을 간과하고 있기 때문에 일어난 일이다. 예를 들어, 여러분이 정말 최신형 1000만원짜리 pc를 하나 장만 했다고 하자. 벌써 생각만 해도 가슴이 두근거릴 일이다. 그런데, 거기에 어떠한 운영체제도 깔려있지 않다고 한다. Windows, MAC, Linux 그 중 어느 하나 깔려있지 않은 pc를 부팅하려고 해보자. 처음 바이오스 세팅 이후, 컴퓨터는 그저 검은 화면만을 띄우고 아무것도 하려 들지 않을 것이다.

 

컴퓨터가 알아들을 수 있는 언어는 오직 하나 "기계어"뿐이다. 기계어가 뭐냐면, 0과 1로 이루어진 신호를 의미한다. 진짜다. 컴퓨터가 진정으로 알아들을 수 있는 것은 그게 다이다. 다만, 이미 기계어로 프로그램을 만드는 시대가 지나갔을 뿐이다. 정말 처음으로 컴퓨터를 만들어 낸 사람들은 기계어를 이용해야만 했을 것이다. 그렇지만, 그들도 그것이 불편했기 때문에, 어셈블리어, Fortan, C언어 같은 것을 만들어 내어 제어를 시작했고, 그런 코드들이 점점 늘어 나기 시작했다. 그것과 더불어 하드웨어의 성능이 폭발적으로 발전했고, 그 결과 컴퓨터를 실제로 작동시키는 기계어들이 편리한 마우스와 모니터 뒤로 숨어버린 것이다.

 

결론적으로 우리가 "컴파일"을 하는 이유를 이전의 그림을 보강해 설명하자면 다음과 같다 :

컴퓨터는 C언어를 모른다.

 

아무튼, "컴파일러"자체도 하나의 프로그램이다. c언어를 기계로 바꾸어 주는 좀 특수한 역할을 할 뿐이다.

결국 c언어라는 것은, 컴퓨터에게 어떤 일을 수행시키기 위한 기초적인 도구인 것이다.

 

자 그러면 이제 드디어, 그 헤더 파일에 무언가를 작성해보자.

/* 
 * Day04.h 
 * 
 * Created on: 2020. 12. 18. 
 * Author: OkRetry */ 
 #ifndef SRC_DAY04_H_ 
 #define SRC_DAY04_H_ 
 
 void test01(); 
 
 #endif /* SRC_DAY04_H_ */

 

이게 뭐냐고 묻기 전에, 일단 다른 소스파일을 하나 더 작성해보자. 이번에는 test01.c라는 이름의 소스파일을 작성하고, Day02.c의 내용도 조금 바꾸어 보자.

<test01.c>

#include"Day04.h" 
#include<stdio.h> 
void test01(){ 
	printf("Executed from test01!"); 
}

 

<Day04.c>

#include"Day02.h" 
#include<stdio.h> 
int main(){ 
	test01(); 
    return 0; 
}

 

이전에 만들던 프로그램이 있으면 [Project] -> [Clean...]을 눌러서 한번 캐시를 날리고 다시 [Build Project]를 한 다음, [Launch]를 하도록 하자.

 

그렇다면, 아래와 같이 콘솔에 글자가 찍힐 것이다.

분명 이상하다. 나는 Day01에서 "main 함수부터 프로그램이 시작하고, return 0에서 끝난다"라고 이야기 했다. 그 사이에 printf는 없었는데, 무엇 때문에 test01.c에 적어둔 글귀가 나타난 것일까?

 

그 비밀을 알기 위해서는 함수가 무엇인가를 알아야 한다. 고등학교 중학교 때에 배우는 함수를 떠올려 보자. "함수"란, 어떠한 수를 입력으로서 받고, 그 수를 이용해 어떤 특정한 동작을 한 다음, 다시 어떤 결과값을 내놓는 과정 자체를 의미한다.

우리는 이 함수의 개념을 좀 더 자유롭게 확장하려고 한다.

저 위의 그림의 f(x)는 많은 사람들에게 친숙한 개념 일 것이다. f(x) 라는 함수가 "x를 제곱한 값을 내보낸다"라고 정의 되어 있으면 다음과 같은 함수가 탄생하는 것이다.

 

그런데, 뭔가 좀... 지루하다. f가 함수이름이라면 뭘하겠다는 건지도, 분간하기도 힘들어지므로, test01이라는 이름을 가진 함수가 만든 것이다. 이렇게 함수이름을 지으면 안되는거 아니냐고 할 수도 있지만, 우린 프로그래머이므로 이런 일을 마음대로 할 수 있다.

728x90
반응형