9 Вывод препроцессора ¶
При использовании C-препроцессора с компиляторами C, C++ или Objective-C, он интегрируется в компилятор и передает поток бинарных токенов напрямую парсеру компилятора. Однако он также может использоваться в более традиционном автономном режиме, где он генерирует текстовый вывод.
Вывод C-препроцессора выглядит очень похоже на входной, за исключением того, что все строки директив препроцессинга заменены пустыми строками, а все комментарии — пробелами. Длинные последовательности пустых строк отбрасываются.
Стандарт ISO определяет, что препроцессор сохраняет пробелы между токенами или заменяет их, например, одним пробелом, как реализация. В GNU CPP пробелы между токенами сводятся к одному пробелу, за исключением того, что первый токен в строке, не являющейся директивой, предваряется достаточным количеством пробелов, чтобы он отображался в том же столбце в выходном препроцессированном файле, что и в исходном файле. Это делается для удобства чтения вывода. CPP не вставляет пробелы там, где их не было в исходном коде, за исключением случаев, когда это необходимо, чтобы предотвратить случайное склеивание токенов.
Информация об имени файла и номере строки передается строками следующего формата
# linenum filename flags
Они называются маркерами строк. Они вставляются по мере необходимости в выходной файл (но никогда не внутри строки или символьного литерала). Они означают, что следующая строка происходит из файла filename в строке linenum. filename никогда не будет содержать непечатных символов; они заменяются восьмеричными последовательностями escape.
После имени файла следует ноль или более флагов, которые представляют собой ‘1’, ‘2’, ‘3’ или ‘4’. Если флагов несколько, они разделены пробелами. Вот что означают флаги:
- ‘1’
Это указывает на начало нового файла.
- ‘2’
Это указывает на возврат к файлу (после включения другого файла).
- ‘3’
Это указывает, что следующий текст происходит из системного заголовочного файла, поэтому следует подавить определенные предупреждения.
- ‘4’
Это указывает, что следующий текст следует рассматривать как заключенный в неявный блок
extern "C".
В качестве расширения препроцессор принимает маркеры строк в файлах ввода, не являющихся файлами ассемблера. Они обрабатываются как соответствующая директива ‘#line’ (см. Управление строками), за исключением того, что разрешены последующие флаги, которые интерпретируются в соответствии с описанными выше значениями. Если задано несколько флагов, они должны быть в порядке возрастания.
Некоторые директивы могут быть продублированы в выводе препроцессора. Это ‘#ident’ (всегда), ‘#pragma’ (только если препроцессор не обрабатывает pragma сам), и ‘#define’ и ‘#undef’ (с определёнными опциями отладки). Если это произойдет, ‘#’ директивы всегда будет в первом столбце, и между ‘#’ и именем директивы пробела не будет. Если расширение макроса приводит к возникновению токенов, которые могут быть ошибочно приняты за дублированную директиву, между ‘#’ и именем директивы будет вставлен пробел.
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-10.5.0/cpp/Preprocessor-Output.html