C언어 컴파일 과정: 두 판 사이의 차이

기술노트
편집 요약 없음
태그: 되돌려진 기여 시각 편집
(컴퓨터 과학 용어 정리 - C언어 컴파일 과정 추가)
태그: 수동 되돌리기
1번째 줄: 1번째 줄:
==== C 언어 컴파일 과정 ====
==== C언어 컴파일 과정 ====


C 언어로 작성된 소스 코드는 여러 단계를 거쳐 컴퓨터가 이해할 수 있는 실행 가능한 바이너리 파일로 변환됩니다. 이 과정은 일반적으로 다음과 같은 4단계로 나뉘며, 대표적인 컴파일러인 `gcc`를 기준으로 설명합니다.
---


 
gcc를 통해 C언어로 작성된 코드가 컴파일되는 과정을 알아보자
위와 같은 단계를 통해 생성된 실행 파일은 메모리(RAM)에 적재되어 운영체제 상에서 실제로 동작하게 됩니다.


<br>
<br>


=== 1. 전처리 (Preprocessing) ===
<img src="https://t1.daumcdn.net/cfile/tistory/254DB03A58326E501C">
 
- `#include` 지시문에 따라 헤더 파일의 내용을 삽입합니다.
- `#define`, `#ifdef`, `#ifndef` 등 매크로를 해석하고 코드에 적용합니다.
- 주석 제거 및 조건부 컴파일 처리도 이 과정에서 수행됩니다.


→ 전처리 결과는 확장자가 `.i`인 중간 코드로 저장됩니다.
이러한 과정을 거치면서, 결과물은 컴퓨터가 이해할 수 있는 바이너리 파일로 만들어진다. 이 파일을 실행하면 주기억장치(RAM)로 적재되어 시스템에서 동작하게 되는 것이다.


<br>
<br>


=== 2. 컴파일 (Compilation) ===
1. #### 전처리 과정


전처리된 코드를 기반으로 어셈블리 코드로 변환하는 단계이며, 내부적으로는 세부적인 세 단계로 구성됩니다:
  - 헤더파일 삽입 (#include 구문을 만나면 헤더파일을 찾아 그 내용을 순차적으로 삽입)
  - 매크로 치환 및 적용 (#define, #ifdef와 같은 전처리기 매크로 치환 및 처리)


* '''전단부 (Front-end)''': 
  <br>
  - 어휘 분석(Lexical Analysis), 구문 분석(Syntax Analysis), 의미 분석(Semantic Analysis)을 수행합니다. 
  - 주로 문법 오류를 탐지하는 역할을 합니다.


* '''중단부 (Middle-end)''': 
2. #### 컴파일 과정 (전단부 - 중단부 - 후단부)
  - SSA(Static Single Assignment) 형태로 변환 후 다양한 최적화를 수행합니다. 
  - 실행 성능을 개선하기 위한 중간 코드 최적화가 이루어집니다.


* '''후단부 (Back-end)'''
  - '''전단부''' (언어 종속적인 부분 처리 - 어휘, 구문, 의미 분석)
  - 대상 시스템 아키텍처에 맞게 최적화된 어셈블리 코드로 변환합니다. 
  - '''중단부''' (SSA 기반으로 최적화 수행 - 프로그램 수행 속도 향상으로 성능 높이기 위함)
  - 불필요한 연산 제거, 명령어 재배치 등을 통해 실행 효율을 극대화합니다.
  - '''후단부''' (RTS로 아키텍처 최적화 수행 - 더 효율적인 명령어로 대체해서 성능 높이기 위함)


→ 결과는 `.s` 확장자의 어셈블리 코드 파일입니다.
  <br>


<br>
3. #### 어셈블 과정


=== 3. 어셈블 (Assembling) ===
  > 컴파일이 끝나면 어셈블리 코드가 됨. 이 코드는 어셈블러에 의해 기계어가 된다.


어셈블리 코드를 기계어(Object Code)로 번역하는 단계입니다.
  - 어셈블러로 생성되는 파일은 명령어와 데이터가 들어있는 ELF 바이너리 포맷 구조를 가짐
    (링커가 여러 바이너리 파일을 하나의 실행 파일로 효과적으로 묶기 위해 `명령어와 데이터 범위`를 일정한 규칙을 갖고 형식화 해놓음)


- 어셈블러는 `.s` 파일을 받아 `.o` 확장자의 오브젝트 파일(Object File)로 변환합니다.
  <br>
- 생성된 오브젝트 파일은 **ELF(Executable and Linkable Format)** 구조를 따르며, 명령어와 데이터가 일정한 규칙으로 정렬되어 있습니다.
- 이 구조는 나중에 링커가 여러 오브젝트 파일과 라이브러리를 효과적으로 결합할 수 있도록 돕습니다.


<br>
4. #### 링킹 과정
 
=== 4. 링킹 (Linking) ===
 
- 여러 개의 오브젝트 파일(.o)과 라이브러리(.lib/.a)를 결합하여 하나의 실행 파일을 만듭니다.
- 함수 호출, 전역 변수 참조 등 서로 연결되지 않은 심볼(Symbol)을 해결합니다.
- 동적 라이브러리를 사용하는 경우 해당 정보를 실행 파일에 포함시킵니다.
 
→ 최종 결과물은 확장자가 `.out`, `.exe`, 또는 사용자 정의 이름의 실행 파일입니다.
 
<br>
 
== 요약 ==
 
{| class="wikitable"
|-
! 단계 !! 입력 파일 !! 출력 파일 !! 주요 도구
|-
| 전처리 || hello.c || hello.i || cpp
|-
| 컴파일 || hello.i || hello.s || cc1
|-
| 어셈블 || hello.s || hello.o || as
|-
| 링킹 || hello.o || a.out (또는 지정 이름) || ld
|}
 
<br>


== 관련 링크 ==
  > 오브젝트 파일들과 프로그램에서 사용된 C 라이브러리를 링크함
  >
  > 해당 링킹 과정을 거치면 실행파일이 드디어 만들어짐


* [GCC 공식 문서](https://gcc.gnu.org/)
  <br>
* [ELF 포맷 위키백과](https://ko.wikipedia.org/wiki/실행_가능_및_연결_형식)

2025년 4월 21일 (월) 14:50 판

C언어 컴파일 과정

---

gcc를 통해 C언어로 작성된 코드가 컴파일되는 과정을 알아보자


<img src="https://t1.daumcdn.net/cfile/tistory/254DB03A58326E501C">

이러한 과정을 거치면서, 결과물은 컴퓨터가 이해할 수 있는 바이너리 파일로 만들어진다. 이 파일을 실행하면 주기억장치(RAM)로 적재되어 시스템에서 동작하게 되는 것이다.


1. #### 전처리 과정

  - 헤더파일 삽입 (#include 구문을 만나면 헤더파일을 찾아 그 내용을 순차적으로 삽입)
  - 매크로 치환 및 적용 (#define, #ifdef와 같은 전처리기 매크로 치환 및 처리)
  

2. #### 컴파일 과정 (전단부 - 중단부 - 후단부)

  - 전단부 (언어 종속적인 부분 처리 - 어휘, 구문, 의미 분석)
  - 중단부 (SSA 기반으로 최적화 수행 - 프로그램 수행 속도 향상으로 성능 높이기 위함)
  - 후단부 (RTS로 아키텍처 최적화 수행 - 더 효율적인 명령어로 대체해서 성능 높이기 위함)
  

3. #### 어셈블 과정

  > 컴파일이 끝나면 어셈블리 코드가 됨. 이 코드는 어셈블러에 의해 기계어가 된다.
  - 어셈블러로 생성되는 파일은 명령어와 데이터가 들어있는 ELF 바이너리 포맷 구조를 가짐
    (링커가 여러 바이너리 파일을 하나의 실행 파일로 효과적으로 묶기 위해 `명령어와 데이터 범위`를 일정한 규칙을 갖고 형식화 해놓음)
  

4. #### 링킹 과정

  > 오브젝트 파일들과 프로그램에서 사용된 C 라이브러리를 링크함
  >
  > 해당 링킹 과정을 거치면 실행파일이 드디어 만들어짐