Namespaces
Variants

Phases of translation

From cppreference.net

C 소스 파일은 컴파일러에 의해 마치 다음 단계들이 정확히 이 순서대로 발생하는 것처럼 처리됩니다. 실제 구현은 동작이 동일하다면 이러한 동작들을 결합하거나 다르게 처리할 수 있습니다.

목차

Phase 1

1) 소스 코드 파일(일반적으로 UTF-8과 같은 멀티바이트 인코딩으로 된 텍스트 파일)의 개별 바이트들은 구현 정의 방식으로 소스 문자 집합 의 문자들에 매핑됩니다. 특히, 운영체제에 종속적인 줄 끝 표시자는 새 줄 문자로 대체됩니다.
소스 문자 집합 은 다음 96개 문자로 구성된 기본 소스 문자 집합 을 단일 바이트 하위 집합으로 포함하는 멀티바이트 문자 집합입니다:
a) 5개의 공백 문자(스페이스, 수평 탭, 수직 탭, 폼 피드, 줄 바꿈)
b) '0' 부터 '9' 까지의 10개 숫자 문자
c) 'a' 부터 'z' 까지 그리고 'A' 부터 'Z' 까지의 52개 문자
d) 29개의 구두점 문자: _ { } [ ] # ( ) < > % : ; . ? * + - / ^ & | ~ ! = , \ " '
2) Trigraph sequences 는 해당하는 단일 문자 표현으로 대체됩니다. (until C23)

2단계

1) 백슬래시가 줄 끝에 나타날 때(바로 뒤에 개행 문자가 오는 경우), 백슬래시와 개행 문자 모두 삭제되어 두 개의 물리적 소스 줄을 하나의 논리적 소스 줄로 결합합니다. 이는 단일 패스 연산입니다: 두 개의 백슬래시로 끝나는 줄 뒤에 빈 줄이 오더라도 세 줄을 하나로 결합하지 않습니다.
#include <stdio.h>
#define PUTS p\
u\
t\
s
/* Line splicing is in phase 2 while macros
 * are tokenized in phase 3 and expanded in phase 4,
 * so the above is equivalent to #define PUTS puts
 */
int main(void)
{
 /* Use line splicing to call puts */ PUT\
S\
("Output ends here\\
0Not printed" /* After line splicing, the remaining backslash
               * escapes the 0, ending the string early.
               */
);
}
2) 비어 있지 않은 소스 파일이 이 단계 이후에 개행 문자로 끝나지 않는 경우(원래 개행 문자가 없었거나 백슬래시로 끝났던 경우), 동작은 정의되지 않습니다.

Phase 3

1) 소스 파일은 comment , 공백 문자 시퀀스(스페이스, 수평 탭, 새 줄, 수직 탭, 폼 피드), 그리고 다음 preprocessing tokens 으로 분해됩니다
a) 헤더 이름: < stdio. h > 또는 "myfile.h"
c) 전처리 숫자(preprocessing numbers) - 이는 정수 상수 부동 소수점 상수 를 포함하지만, 또한 1 .. E + 3. foo 또는 0JBK 와 같은 일부 유효하지 않은 토큰도 포함합니다.
e) 연산자와 구두점, 예를 들어 + , <<= , < % , 또는 ## .
f) 다른 어떤 범주에도 속하지 않는 개별 공백이 아닌 문자
2) 각 주석은 하나의 공백 문자로 대체됩니다
3) 줄 바꿈은 유지되며, 줄 바꿈이 아닌 공백 시퀀스가 단일 공백 문자로 축소될 수 있는지는 구현에 따라 정의됩니다.

입력이 주어진 문자까지 전처리 토큰으로 파싱되었다면, 일반적으로 다음 전처리 토큰은 이후 분석이 실패하더라도 전처리 토큰을 구성할 수 있는 가장 긴 문자 시퀀스로 간주됩니다. 이것은 일반적으로 maximal munch 로 알려져 있습니다.

int foo = 1;
// int bar = 0xE+foo; // 오류: 유효하지 않은 전처리 숫자 0xE+foo
int bar = 0xE/*주석은 공백으로 확장됨*/+foo; // OK: 0xE + foo
int baz = 0xE + foo; // OK: 0xE + foo
int pub = bar+++baz; // OK: bar++ + baz
int ham = bar++-++baz; // OK: bar++ - ++baz
// int qux = bar+++++baz; // 오류: bar++ ++ +baz, bar++ + ++baz가 아님
int qux = bar+++/*주석 삽입*/++baz; // OK: bar++ + ++baz

최대한 많이 적용 규칙의 유일한 예외는 다음과 같습니다:

#define MACRO_1 1
#define MACRO_2 2
#define MACRO_3 3
#define MACRO_EXPR (MACRO_1 <MACRO_2> MACRO_3) // OK: <MACRO_2>는 헤더 이름이 아님

페이즈 4

1) Preprocessor 가 실행됩니다.
2) #include 지시문으로 도입된 각 파일은 1단계부터 4단계까지 재귀적으로 진행됩니다.
3) 이 단계가 끝나면 모든 전처리기 지시문이 소스에서 제거됩니다.

페이즈 5

1) 모든 문자와 escape sequences character constants string literals 내에서 source character set 에서 execution character set 으로 변환됩니다(이는 UTF-8과 같은 멀티바이트 문자 집합일 수 있으며, 1단계에 나열된 basic source character set 의 96개 문자 모두가 단일 바이트 표현을 가지는 한). escape sequence로 지정된 문자가 execution character set의 구성원이 아닌 경우, 그 결과는 구현에 따라 정의되지만 null (wide) character가 아니라는 것이 보장됩니다.

참고: 이 단계에서 수행되는 변환은 일부 구현체에서 명령줄 옵션으로 제어할 수 있습니다: gcc와 clang은 - finput - charset 를 사용하여 소스 문자 집합의 인코딩을 지정하고, - fexec - charset - fwide - exec - charset 를 사용하여 문자열 리터럴과 문자 상수에서 인코딩 접두사가 없는 (C11부터) 실행 문자 집합의 인코딩을 지정합니다.

페이즈 6

인접한 string literals 은 연결됩니다.

Phase 7

컴파일이 수행됩니다: 토큰들이 구문 및 의미론적으로 분석되고 번역 단위로 변환됩니다.

페이즈 8

링킹이 발생합니다: 외부 참조를 충족시키기 위해 필요한 번역 단위와 라이브러리 구성 요소들이 프로그램 이미지로 수집되며, 이 이미지는 실행 환경(운영 체제)에서 실행에 필요한 정보를 포함합니다.

참고문헌

  • C23 표준 (ISO/IEC 9899:2024):
  • 5.1.1.2 번역 단계 (p: TBD)
  • 5.2.1 문자 집합 (p: TBD)
  • 6.4 어휘 요소 (p: TBD)
  • C17 표준 (ISO/IEC 9899:2018):
  • 5.1.1.2 번역 단계 (p: 9-10)
  • 5.2.1 문자 집합 (p: 17)
  • 6.4 어휘 요소 (p: 41-54)
  • C11 표준 (ISO/IEC 9899:2011):
  • 5.1.1.2 번역 단계 (p: 10-11)
  • 5.2.1 문자 집합 (p: 22-24)
  • 6.4 어휘 요소 (p: 57-75)
  • C99 표준 (ISO/IEC 9899:1999):
  • 5.1.1.2 번역 단계 (p: 9-10)
  • 5.2.1 문자 집합 (p: 17-19)
  • 6.4 어휘 요소 (p: 49-66)
  • C89/C90 표준 (ISO/IEC 9899:1990):
  • 2.1.1.2 번역 단계
  • 2.2.1 문자 집합
  • 3.1 어휘 요소

참고 항목

C++ 문서 참조: 번역 단계