C 프로그램 빌드 과정과 각 단계의 역할

edward·2025년 10월 16일

1. 프리프로세싱 단계 (Preprocessor: #include 처리)

  • 역할: 소스 코드를 컴파일러가 처리하기 쉬운 형태로 텍스트 치환 및 확장합니다.
  • 결과: #include <stdio.h>와 같은 지시문을 만나면, stdio.h와 같은 헤더 파일의 내용이 메인 소스 파일에 복사되어 들어옵니다.
  • 포함되는 내용: 이 헤더 파일에는 주로 printf와 같은 함수의 선언 (Declaration), 즉 함수의 이름, 반환 타입, 매개변수 정보만 포함되어 있습니다. 함수의 실제 구현 코드(바디)는 포함되어 있지 않습니다.

2. 컴파일 단계 (Compiler: 목적 파일 생성)

  • 역할: 확장된 소스 코드를 읽어 기계어 코드로 번역하고 목적 파일(.o)을 생성합니다.
  • 처리: 컴파일러는 printf() 호출을 만나면, 선언을 통해 그 형태가 유효함을 확인하고, 이 함수가 "외부 어딘가에 정의되어 있다"는 심볼(Symbol) 참조 정보만 목적 파일에 남깁니다.

3. 링킹 단계 (Linker: 최종 결합)

  • 역할: 여러 목적 파일과 라이브러리를 하나로 결합하여 실행 파일을 만듭니다.
  • 처리:
    • 링커는 목적 파일들을 검사하여 printf와 같이 정의가 없는 심볼(Undefined Symbols) 목록을 확인합니다.
    • 이 심볼들을 해결하기 위해 표준 라이브러리 파일(libc.a 또는 libc.so)을 탐색합니다.
    • 라이브러리 파일 내에 미리 컴파일된 printf 함수의 구체적인 구현체 (이진 코드)가 정의되어 있습니다.
    • 링커는 이 구현체의 주소를 사용자 코드의 printf 호출 위치와 연결(Link)해줍니다.

결론적으로:

  • 프리프로세서는 선언을 붙여주고,
  • 링커는 구현체를 연결해 주는 역할을 수행하는 것입니다.

따라서 링커 단계가 되어서야 프로그램이 필요로 하는 모든 코드(사용자 코드 + 시스템/라이브러리 구현체)가 하나로 합쳐져 실행 가능한 파일이 됩니다.

profile
there ain't no shortcuts

0개의 댓글