Namespaces
Variants

Phases of translation

From cppreference.net

Исходный файл на языке C обрабатывается компилятором как если бы следующие этапы выполнялись именно в таком порядке. Фактическая реализация может комбинировать эти действия или обрабатывать их иначе, при условии сохранения того же поведения.

Содержание

Фаза 1

1) Отдельные байты исходного файла (который обычно является текстовым файлом в некоторой многобайтовой кодировке, такой как UTF-8) отображаются, определяемым реализацией способом, в символы исходного набора символов . В частности, зависящие от ОС индикаторы конца строки заменяются символами новой строки.
Исходный набор символов является многобайтовым набором символов, который включает базовый исходный набор символов как однобайтовое подмножество, состоящее из следующих 96 символов:
a) 5 пробельных символов (пробел, горизонтальная табуляция, вертикальная табуляция, прогон страницы, новая строка)
b) 10 цифровых символов от '0' до '9'
c) 52 буквы от 'a' до 'z' и от 'A' до 'Z'
d) 29 знаков пунктуации: _ { } [ ] # ( ) < > % : ; . ? * + - / ^ & | ~ ! = , \ " '
2) Триграфные последовательности заменяются соответствующими односимвольными представлениями. (до 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) Если непустой исходный файл не заканчивается символом новой строки после этого шага (независимо от того, не имел ли он новой строки изначально, или заканчивался обратной косой чертой), поведение не определено.

Фаза 3

1) Исходный файл разлагается на комментарии , последовательности пробельных символов (пробел, горизонтальная табуляция, новая строка, вертикальная табуляция и перевод страницы), и preprocessing tokens , которые представляют собой следующие элементы
а) имена заголовочных файлов: < stdio. h > или "myfile.h"
c) препроцессорные числа, которые включают целочисленные константы и вещественные константы , но также включают некоторые некорректные токены, такие как 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

Единственное исключение из правила максимального захвата:

  • Токены предварительной обработки имени заголовка формируются только внутри #include или #embed (начиная с C23) директивы, в __has_include и __has_embed выражениях (начиная с C23) и в определяемых реализацией местах внутри #pragma директивы.
#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) Препроцессор выполняется.
2) Каждый файл, подключаемый с помощью директивы #include , проходит через фазы с 1 по 4 рекурсивно.
3) В конце этой фазы все директивы препроцессора удаляются из исходного кода.

Фаза 5

1) Все символы и escape-последовательности в символьных константах и строковых литералах преобразуются из исходной кодировки символов в исполнительную кодировку символов (которая может быть многобайтовой кодировкой, такой как UTF-8, при условии что все 96 символов из базовой исходной кодировки символов , перечисленные на фазе 1, имеют однобайтовые представления). Если символ, указанный escape-последовательностью, не является членом исполнительной кодировки символов, результат определяется реализацией, но гарантированно не является нулевым (широким) символом.

Примечание: преобразование, выполняемое на этом этапе, может управляться параметрами командной строки в некоторых реализациях: gcc и clang используют - finput - charset для указания кодировки исходного набора символов, - fexec - charset и - fwide - exec - charset для указания кодировок исполнительного набора символов в строковых литералах и символьных константах без префикса кодировки (начиная с C11) .

Фаза 6

Смежные строковые литералы объединяются.

Фаза 7

Компиляция происходит: токены синтаксически и семантически анализируются и переводятся как единица трансляции.

Фаза 8

Связывание происходит: единицы трансляции и компоненты библиотек, необходимые для удовлетворения внешних ссылок, собираются в программный образ, который содержит информацию, необходимую для выполнения в его среде выполнения (ОС).

Ссылки

  • Стандарт C23 (ISO/IEC 9899:2024):
  • 5.1.1.2 Фазы трансляции (стр.: TBD)
  • 5.2.1 Наборы символов (стр.: TBD)
  • 6.4 Лексические элементы (стр.: TBD)
  • Стандарт C17 (ISO/IEC 9899:2018):
  • 5.1.1.2 Фазы трансляции (стр: 9-10)
  • 5.2.1 Наборы символов (стр: 17)
  • 6.4 Лексические элементы (стр: 41-54)
  • Стандарт C11 (ISO/IEC 9899:2011):
  • 5.1.1.2 Фазы трансляции (стр: 10-11)
  • 5.2.1 Наборы символов (стр: 22-24)
  • 6.4 Лексические элементы (стр: 57-75)
  • Стандарт C99 (ISO/IEC 9899:1999):
  • 5.1.1.2 Фазы трансляции (стр: 9-10)
  • 5.2.1 Наборы символов (стр: 17-19)
  • 6.4 Лексические элементы (стр: 49-66)
  • Стандарт C89/C90 (ISO/IEC 9899:1990):
  • 2.1.1.2 Фазы трансляции
  • 2.2.1 Наборы символов
  • 3.1 Лексические элементы

Смотрите также

C++ documentation для Phases of translation