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-11.4.0/cpp/Preprocessor-Output.html