본문 바로가기

Computer Engineering

[C] 0x02 컴파일러(Compiler) , 링커(Linker), 이스케이프 문자열(Escape Sequence) ...

= 컴파일러 =
컴파일러는 번역기라고 할 수 있는데 과연 '무엇'을 '무엇'으로 번역할까?
사람들이 알아볼 수 있는 '소스파일'을 기계가 알아볼 수 있는 '기계어파일'로 번역하는 것이다. 
 

우리가 사용하는 언어 --> 기계어

                                 |
                          (통역을 해주는 역할)

이와 같이 컴파일(번역,통역)을 해주는 이유는?
: '컴퓨터'라는 기계는 0과 1(이진수) 밖에 모른다.
ON과 OFF 아니면 +, -밖에는 모르는 단순한 기계라고 할 수 있다.
반면 사람은 숫자나 문자로만 모든 것을 이해한다. 그래서 사람들은 자신들이 알아볼 수 있도록 숫자와 문자로 명령을 기록하는데, 이를 기계가 이해할 수 있는 언어인 기계어로 번역해주는 프로그램이 컴파일러입니다. 즉 ABC를 0과 1의 조합으로 바꾸어주는 것입니다.  


ex) first.c --(compile)--> first.obj

위의 예에서 first.obj 는 '목적파일' 이라고 불린다.
이처럼 1개의 Source 파일은 1개의 목적파일을 생성한다.

목적파일 *.obj 파일을 만들어 사용하는 이유?

C로 프로그램을 짜면
~~~.c --> ~~~.obj --> ~~~.exe
           |                   |
      (컴파일)          (링킹)

왜 한번에 바로 소스파일을 *.exe 파일로 만들지 않고 *.obj라는 중간파일을 만드는 것일까? 

프로그램을 좀 더 편하게 만들기 위해서이다. 이래도 이해가 안 될 수 있으므로 간단한 예를 알아보자.

1. 소스파일의 보안을 유지하면서 기능만 제공할 수 있다.

(가)라는 사람이 시계 프로그램을 C언어로 짠 뒤에 이를 clock.exe라는 실행 프로그램으로 만들었다. 그리고 (나)라는 사람이 사람은 달력프로그램을 만들어서 calendar.exe로 만들었다고 하자. (나)는 (가)가 만든 시계프로그램과 자신의 달력프로그램 합쳐서 cc.exe라는 새로운 달력프로그램을 만들고 싶어한다. 가장 좋은 방법은 clock.exe의 C언어 소스파일을 제공받아서 자신의 달력프로그램에 합친 후에 이를 컴파일하고 링크해서 cc.exe를 만드는 방법일 것이다. 

그러나 소스파일이라는 것은 그 사람이 지닌 고도의 기술과 경험에 해당하며 일종의 회사기밀이다. 프로그램의 소스 자체가 가장 중요한 재산이므로 프로그래머는 함부로 이를 공개하지 않는다. 그래서 (가)는 소스파일 대신에 중간파일인 clock.obj를 (나)에게 제공한다. 그럼 (나)는 clock.obj와 calendar.obj를 링커 프로그램으로 연결(linking)해서 cc.exe 파일을 만들 수 있다. 보안성도 유지되고 서로 각기 다른 프로그램을 만들어서 합칠 수 있으므로 효율적이다. 


2: 분업화, 모듈화가 가능하다.

꼭 보안성 문제 때문만은 아니다. obj파일을 이용하면 하나의 프로그램을 짤 때 열 명이 각기 다른 기능을 가진 프로그램을 짜도된다. (가)는 시계프로그램을 짜고, (나)는 달력프로그램을 (다)는 문서편집프로그램을 짠 뒤에 각기 짠 프로그램을 *.obj 파일로 만들어서 총기획자에게 보내주면 작업이 끝납니다. 프로그램 기획자는 (가) (나) (다)로부터 받은 세 개의 파일을 링크프로그램으로 연결만 하면 되기 때문이다. 

따라서 하나의 프로그램을 혼자서 낑낑 대며 짤 필요가 없다. 여러 명에게 나누어 준 뒤에 나중에 합치기만 하면 되므로 인력을 효율적으로 관리할 수 있으며 프로그램 개발에 걸리는 시간이 줄어든다. 만약 하나의 소스로 방대한 프로그램을 짜야 한다면 한 사람이 방대한 소스파일의 내용을 모두 파악하고 있어야 하며, 한 사람이 모두 짜야 하므로 시간이 무척 오래 걸리게 된다. 

또한 프로그램을 만드는 실무자들은 자신이 맡은 부분만 담당하게 되므로 프로그램 전체의 기밀을 유지하는데도 도움이 된다. 


3: 컴파일 시간 등을 줄일 수 있다.

보안과 분업화라는 기업적인 측면의 장점 외에도 개인에게 도움이 되는 장점이 있다. 목적파일을 만들어 사용하면 컴파일 시간을 줄일 수 있다는 점이다. 

요즘은 컴퓨터와 언어프로그램이 워낙 좋아져서 컴파일하는 시간이 많이 안걸리지만 예전에는 프로그램 하나 컴파일하는데 하루 종일 걸렸다. 지금도 조금 덩치가 큰 프로그램을 컴파일할 때는 몇 십분에서 몇 시간씩 걸린다. 소스 길이가 몇 만 줄, 몇 십 만 줄이나 되는 덩치 큰 프로그램을 개발한다고 생각해보시면 이해가 될 것이다. 몇 십 만 줄에서 한 줄 고치고 컴파일하면서 몇 십분 또는 몇 시간씩 기다려야 한다면 얼마나 시간낭비일까? 

그래서 문제가 없는 프로그램이나 함수 부분을 컴파일해서 *.obj 파일로 만들어놓는다. 그리고 새로 고친 부분이나 새롭게 추가한 부분만 컴파일을 합니다. 그러면 몇 십분씩 걸리는 컴파일 시간이 몇 초로 줄어든다. 이렇게 해서 이상이 없으면 다시 *.obj 파일로 만들어놓고, 또 새로운 함수나 프로그램을 만든다. 그리고 나중에 최종적으로 그동안 만든 *.obj 파일을 하나로 링크시키기만 하면된다. 이렇게 *.obj 파일을 이용해서 컴파일을 하면 컴파일 시간이 획기적으로 줄어든다. 

만약 *.obj 파일을 사용하지 않고 바로 *.exe 파일을 만들어야 한다면 단 한 줄을 고치고도 수 십 만 줄이나 되는 소스파일을 전부 컴파일하느라고 많은 시간을 낭비해야 한다. 또한 한꺼번에 수 십 만 줄을 읽을 수 있는 비싼 에디터를 써야 하며, 빠른 컴파일을 위해 컴퓨터도 매우 높은 사양의 기종으로 갖추어야 한다. 

4: 확장성과 이식성을 높일 수 있습니다.

그 외에도 obj 파일을 이용할 때의 장점은 많다. 시계프로그램을 clock.obj로 한 번 만들어두었다면 다른 프로그램을 짤 때는 시계프로그램을 다시 짤 필요가 없습니다. 나중에 링크를 할 때 clock.obj 파일만 연결시켜주면 간단하게 해결되기 때문이다. 따라서 이식성이 매우 높아집니다. 

또한 유용한 함수나 소스파일을 컴파일하여 목적파일로 만든 다음에 목적파일만 합쳐놓은 라이브러리 파일을 만들어 사용할 경우 다양한 기능의 함수를 손쉽게 확장시킬 수 있다. 대표적인 것이 한글 라이브러리이다. 한글 라이브러리를 이용하면 따로 한글을 구현하는 방법을 직접 구현하지 않더라도 다른 사람이 만들어놓은 라이브러리를 이용해서 손쉽게 한글을 구현할 수 있다. 이와 같은 확장성 때문에 프로그램을 만들 때 목적파일을 만들어 사용하는 것이다. 

**요약: 목적파일을 만들어 사용하는 이유는 소스파일의 보안, 작업의 분업화, 프로그램의 모듈화, 이식성과 확장성을 높이기 위해서이다.


= 링크와 링커 프로그램 =

목적파일을 연결해 실행파일로 만드는 일을 링크
라고 하며, 링크작업을 해주는 프로그램을 링커라고 한다.

중간중간 소스파일을 컴파일해서 *.obj 파일로 만들어주는 프로그램을 컴파일러(번역기)라 하고, 목적 파일로 만드는 과정을 '컴파일한다'고 표현한다. 그리고 중간 목적파일인 obj 파일을 연결해서 최종적으로 하나의 실행파일로 만들어주는 프로그램을 링커(Linker)라고 하고, 실행파일로 만드는 과정을 '링크시킨다(Linking)'라고 말한다. 이렇게 obj 파일을 링커 프로그램으로 링크시키면 비로소 실행파일이 만들어지는 것입니다. 

다양한 링커 프로그램이 있으며 프로그램의 성격에 맞는 링커를 선택해 사용합니다

컴파일러 프로그램이 여러 종류인 것처럼 링커 프로그램 역시 수 십 종류가 있습니다.
예) 마이크로소프트C에서 사용하는 MS링크, 터보C에서 사용하는 터보링크, 클리퍼 프로그램에서 사용하는 RT링크와 B링크 프로그램 등

이처럼 다양한 링커 프로그램이 있는 이유는 링커마다 성능과 기능이 조금씩 다르기 때문입니다. 초보자에게는 어렵지만 조금 수준이 높아지면 자신에게 맞는 링커 프로그램을 이용하게 된다. 

과거에는 컴파일을 한 다음에 따로 링킹 과정을 거쳤다. 그러나 통합개발환경이 된 지금은 통합개발 프로그램 안에서 컴파일과 링킹 과정을 하나의 과정으로 연속 처리해준다. 따라서 별도로 링커 프로그램을 구할 필요도 없으며, 따로 링킹시킬 필요도 없다. 물론 라이브러리 파일이라는 것을 만들 때에는 별도로 링커 프로그램을 이용해야 한다. 

**요약: 컴파일러로 컴파일을 하면 *.obj 파일이 만들어지는데 이를 연결(link)해서 실행파일인 *.exe 파일로 만들어주는 프로그램을 링커(linker)라고 한다. 
 
[출처 : IT문화원 ] 


= Build =


Windows 에서는 Visual Studio 로 작업을 하게 되는데 'Build' 라는 것을 볼 수 있다.
Build 는 위에서 이야기한 Compile(컴파일) 과  Linking(링킹) 과정을 합친것이라고 생각하면 쉽게 이해할 수 있다.

이제 본격적인 C 언어로 들어가서
 

= escape sequence (이스케이프 문자열) =
프린터나 모니터의 화면 속성 등을 제어하기 위해 장치에 보내는 특수 문자열을 의미하는데, 그 중에서도 특히 이스케이프 문자로 시작되는 기계 명령을 말한다. [출처 : 텀즈 ]
\ <= 이 녀석이 바로 이스케이프 문자 ㅎㅎ

오늘 실습한 코드를 잠시 살펴보자. [Big_Character.c]

#include <stdio.h>

int main()
{
    printf("\t\tA\n");
    printf("\tB\t\tC\n");
    printf("D\t\tE\t\tF\n");
    printf("\tG\t\tH\n");
    printf("\t\tI\n");

    return 0;
}

jack2@Security:~/바탕화면/C/0x02$ ./Big_Character 
A
B C
D E F
G H
I

=> 이런 모양으로 출력되는 것을 확인할 수 있다. 그 이유는 \ 가 들어간 Escape Sequence (이스케이프 문자열)을 사용했기 때문이다.

\t => tab 과 같은 역할을 한다. 보통 8칸이 띄워쓴 것과 같다.
\n => enter 와 같이 행바꿈 역할을 한다.


또 하나의 예를 보자면 [Error_Sound.c]

#include <stdio.h>

int main()
{
    printf("Error!! a\bb\n");

    return 0;
}

jack2@Security:~/바탕화면/C/0x02$ ./Error_Sound 
Error!! b

=> 이렇게 결과가 나온다. 뭥미? 
printf("Error!! a\bb\n"); 이렇게 적었는데 a 는 어디로 사라진 것인가? 라고 이야기 할 수 있다. 하지만 이것도 이스케이프 문자열을 사용했기 때문이다.  printf 함수안의 내용을 보면 ("Error!! a\bb\n"); 이라고 적혀있는데
Error!! 뒤에  a\bb\n 
                       |       
                      백스페이스 역할을 한다. 그래서 a 문자 바로 다음 백스페이스를 눌렀으므로 a 를 지우고 b 만 출력이 되는 것이다.

printf 문에서 ",',\ 문자를 출력하려고 하면 \",\',\\ 이렇게 입력을 해주어야 출력을 할 수 있다.

다음으로 C 언어의 특징 ! 소스코드의 위에서 아래로 실행이 되는 절차지향언어이다.

그리고 Windows 에서 작업시 Visual Studio 에서  하나의 Project를 생성해서 여러개의 Source(소스)를 넣을 수 있다. 하지만 유의사항이 하나있다.

원래 Ctrl+F5 를 누르면 Build 를 할 수 있다.
하지만 
1.c , 2.c , 3.c ... 등 등 모든 소스에 int main() 이 정의되어 있다면 문제가 된다.

int main() => 프로그램의 시작점을 이야기하는 것이다. 그런데 여러개의 main 이 있다면 시작점이 여러개라는 것인데 ... 그 말은 즉, 시작점이 여러개 있다는 것인데 프로그램 실행할 때 어디부터 시작할지 정할 수 없는것이다.

그래서 여러 시작점을 제거하고 단 하나의 시작점을 만들어 주어야 한다.
예를 들어 실행할 소스가 1.c 라고 하면 나머지 2.c , 3.c ... 등의 소스의 [속성] 에서 '빌드에서 제외' 라는 부분을 아니오 -> 예 로 바꾸어 준 뒤 Ctrl + F5 를 누른다면 Build 가 되어서 실행이 되는 것을 확인할 수 있다.


'Computer Engineering' 카테고리의 다른 글

[C] 0x05 연산자(Operator)  (0) 2012.01.11
[C] 0x03 DataType(자료형)  (0) 2012.01.09
[C] 0x01  (0) 2012.01.05
Emacs 명령어  (0) 2011.11.15
[C++] const 상수로 정의하면  (0) 2011.11.08