Связанная статья полна основных ошибок, и на нее не следует полагаться.
Процесс синтаксического анализа C или C ++ определяется как последовательность преобразований: 1
- Обратная косая черта - новая строка заменяется ничем - даже пробелом.
- Комментарии удаляются и заменяются одним пробелом.
- Оставшийся в живых текст преобразуется всерия токенов предварительной обработки .Они менее специфичны, чем токены, используемые самим языком: например, ключевое слово
if
является токеном IF для самого языка, но является просто токеном IDENT препроцессору. - Выполняются директивы предварительной обработки имакросы раскрываются.
- Каждый токен предварительной обработки преобразуется в токен.
- поток токенов анализируется в абстрактном синтаксическом дереве, а остальная часть компилятора берет его оттуда.
Ваша программа-пример
#include<stdio.h>
#define max 100
int main()
{
printf("max is %d", max);
return 0;
}
после преобразования 3 будет представлять собой серию из 23 токенов предварительной обработки:
PUNCT:# IDENT:include INCLUDE-ARG:<stdio.h>
PUNCT:# IDENT:define IDENT:max PP-NUMBER:100
IDENT:int IDENT:main PUNCT:( PUNCT:)
PUNCT:{
IDENT:printf PUNCT:( STRING:"max is %d" PUNCT:, IDENT:max PUNCT:) PUNCT:;
IDENT:return PP-NUMBER:0 PUNCT:;
PUNCT:}
На этом этапе все еще присутствуют директивы,Обратите внимание, что #include
и #define
- это каждый два токена: #
и имя директивы являются отдельными.Некоторым людям нравится писать сложные #if
гнезда с хеш-метками, все в столбце 1, но имена директив с отступом.
После преобразования 5 директивы исчезли, и у нас есть 16 + n токенов этой серии:
[ ... some large volume of tokens produced from the contents of stdio.h ... ]
INT IDENT:main LPAREN RPAREN
LBRACE
IDENT:printf LPAREN STRING:"max is %d" COMMA DECIMAL-INTEGER:100 RPAREN SEMICOLON
RETURN DECIMAL-INTEGER:0 SEMICOLON
RBRACE
, где 'n' равно количеству токенов, полученных из stdio.h.
Директивы предварительной обработки (#include
, #define
, #if
и т. Д.) всегда удаляются из потока токенов и, возможно, заменяются чем-то другим, так что после преобразования 6 у вас никогда не будет токенов, которые являются прямым результатом текста директивной строки.Но у вас обычно будут токены, которые являются результатом эффектов каждой директивы, таких как содержимое stdio.h
и DECIMAL-INTEGER:100
, заменяющих IDENT:max
.
Наконец, C и C ++сделать эту серию операций почти , но не совсем, то же самое, и спецификации формально независимы.Обычно вы можете полагаться на операции предварительной обработки, чтобы вести себя одинаково на обоих языках, если вы выполняете только простые операции с препроцессором, что в любом случае является наилучшей практикой в настоящее время.
1 Иногда вы увидите, как люди говорят о фазах перевода , именно так стандарты C и C ++ официально описывают эту серию операций.Мой список не список этапов перевода;он включает отдельные пункты для некоторых вещей, которые по стандартам сгруппированы в одну фазу, и пропускает несколько шагов, не относящихся к данному обсуждению.