Этапы трансляции
Файл исходного кода C обрабатывается компилятором как если бы выполнялись следующие этапы в точном порядке. Фактическая реализация может объединять эти действия или обрабатывать их по-разному, при условии сохранения одинакового поведения.
Этап 1
'0' до '9'
'a' до 'z' и от 'A' до 'Z'
_ { } [ ] # ( ) < > % : ; . ? * + - / ^ & | ~ ! = , \ " '
Этап 2
#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.
*/
);
}Этап 3
<stdio.h> или "myfile.h"
1..E+3.foo или 0JBK
+, <<=, <%, или ##.Если входной файл был проанализирован в предпроцессорные токены до заданного символа, то следующим предпроцессорным токеном, как правило, считается самая длинная последовательность символов, которая может составлять предпроцессорный токен, даже если это приведет к последующему анализу с ошибкой. Это обычно известно как максимальное поглощение.
int foo = 1; // int bar = 0xE+foo; // error: invalid preprocessing number 0xE+foo int bar = 0xE/*Comment expands to a space*/+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; // error: bar++ ++ +baz, not bar++ + ++baz int qux = bar+++/*Saving comment*/++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> is not a header-name
Этап 4
Этап 5
Примечание: преобразование, выполняемое на данном этапе, может контролироваться параметрами командной строки в некоторых реализациях: gcc и clang используют -finput-charset для указания кодировки исходного набора символов, -fexec-charset и -fwide-exec-charset для указания кодировок набора символов выполнения в строковых литералах и символьных константах без префикса кодировки(с C11).
Этап 6
Смежные строковые литералы конкатенируются.
Этап 7
Происходит компиляция: токены анализируются с точки зрения синтаксиса и семантики и переводятся как единица трансляции.
Этап 8
Происходит компоновка: единицы трансляции и необходимые библиотечные компоненты для удовлетворения внешних ссылок собираются в образ программы, который содержит информацию, необходимую для выполнения в среде выполнения (ОС).
Ссылки
- Стандарт C23 (ISO/IEC 9899:2023):
- 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++ для Этапов трансляции |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/c/language/translation_phases