C언어 | 컴파일 4단계(GCC), 컴파일러 vs 인터프리터

설탕·2024년 3월 7일
0
post-thumbnail

컴파일

인간이 이해할 수 있는 고수준 언어(C, C++, Java 등)로 작성된 소스 코드를 컴파일러를 통해 CPU가 이해할 수 있는 저수준 언어(기계어)로 변환하는 과정이다.

GCC

C언어 실행 환경을 세팅하기 위해 Visual Studio Code에서 익스텐션을 설치해서 GCC로 컴파일을 할 수 있게 되었다.

GCC는 처음에는 C 컴파일러 GNU C Compiler였으나 이후에 C++ 등 다른 언어도 지원하게 되면서 GNU Compiler Collection으로 이름이 변경되었다.

컴파일 4단계

GCC의 컴파일 과정은 전처리 - 컴파일 - 어셈블 - 링크 4단계로 이루어진다.

간단한 .c 파일을 하나 생성해서 어떻게 컴파일되는지 살펴보자!

#include <stdio.h>

int main(void)
{
  printf("Hello, World!\n");

  return 0;
}

1. 전처리기 (Preprocessor)

전처리 지시자(#include)에 따라 소스 파일을 가공한다. 프로그램에 필요한 헤더 파일을 소스 코드로 복사하고, 주석을 삭제하고, #define 매크로를 실행하는 등 소스 파일을 컴퓨터에 맞게 편집한다.

$ gcc -E main.c -o main.i

전처리기를 실행하고 생성된 .i 파일을 열어보면...

#includestdio.h 헤더 파일이 쭉 복사되어 무려 551줄이나 main 함수 위에 들어가 있는 걸 확인할 수 있다.

2. 컴파일러 (Compiler)

고수준 언어를 저수준 언어로 나타내는 역할이다. 전처리된 파일을 어셈블리어로 바꿔준다. 어셈블리어는 기계어를 사람이 이해할 수 있게 부호화한 것이다.

$ gcc -S main.i -o main.s

어셈블리어로 변환된 .s파일이다. 사람이 이해할 수 있는 언어지만 나는 이해할 수 없다...
컴파일 과정에서 최적화를 수행하기 때문에 .i 파일보다 훨씬 코드가 짧아졌다.

3. 어셈블러 (Assembler)

어셈블리어를 기계어로 바꾸는 과정을 수행한다. 어셈블 과정을 거치면 오브젝트 파일(Object File)로 변환된다. 오브젝트 파일은 CPU가 해석할 수 있는 명령어(기계어)로 이루어져 있어서 사람이 읽을 수 없다.

$ gcc -c main.s -o main.o

말 그대로 진짜 읽을 수 없게 되었다.

4. 링커 (Linker)

오브젝트 파일들과 프로그램 실행에 필요한 라이브러리 파일들을 결합해서 하나의 실행 파일로 만든다. 이 실행 파일은 이제 운영체제가 인식하고 실행할 수 있는 파일이다.

$ gcc main.o -o main.exe

우리가 흔히 보던 .exe 실행 파일이다.

컴파일러 vs 인터프리터

컴파일을 수행하는 프로그램으로는 컴파일러와 인터프리터가 있다.

컴파일러 (Compiler)인터프리터 (Interpreter)
런타임 전에 전체 소스 코드를 컴파일해서 기계어로 변환런타임에 한 번에 한 문장씩 변환
컴파일 시간이 걸리지만 실행은 빠름시작은 빠르지만 한 문장씩 변환하면서 실행하기 때문에 실행이 느림
링킹(Linking)이 필요한 Object Code를 생성하여 더 많은 메모리가 필요함Object Code가 만들어지지 않아 메모리 효율이 높음
컴파일 과정에서 전체 코드를 검사하고 에러를 감지하므로 실행 전에 에러 발견 가능함첫 에러를 만날 때까지 프로그램을 계속 번역하고 에러를 만나면 중지하는 방식으로, 실행 전에 에러 발견하기 어려움
컴파일 언어: C, C++, Java, TypeScript 등인터프리터 언어: JavaScript, Python, Ruby 등

컴파일 언어는 바로 기계어로 변환되지만, 인터프리터 언어는 인터프리터가 해석할 수 있는 이진 표현법인 Byte Code로 먼저 변환된 후에 기계어로 변환된다.
그래서 파이썬 같은 인터프리터 언어가 C나 C++와 같은 컴파일 언어보다 상대적으로 느린 것!

자바스크립트는 인터프리터 언어?

자바스크립트는 인터프리터 언어이지만 꼭 인터프리터로만 처리되는 것은 아니다.
크롬 브라우저(또는 Node.js)의 V8 엔진에서는 JIT (Just-In-Time) Compiler 방식으로 자바스크립트를 처리한다. 인터프리터로 컴파일해서 Byte Code로 만들고 이 Byte Code를 캐싱하는 등 최적화해서 컴파일할 때 다시 참조하는 방식으로, 인터프리터보다 더 빠른 속도로 실행 가능하다.

참고
컴파일(Compile)에 대한 이해
[C/C++] GCC가 무엇인가요? GCC의 컴파일 과정 4단계
[C언어] 컴파일 과정(COMPILE PROCESS) 4단계 자세한 설명
컴파일이란 무엇이며, 자바스크립트는 인터프리터 언어인가?
(Term) Compiler VS Interpreter
V8 에서 Javascript 코드를 실행하는 방법 정리해보기

profile
공부 기록

0개의 댓글