Spec-Zone.ru › GCC 11 CPP

Далее: Токенизация, Предыдущее: Наборы символов, Вверх: Обзор [Оглавление][Указатель]

1.2 Первичная обработка ¶

Препроцессор выполняет ряд текстовых преобразований входных данных. Эти преобразования происходят до любой другой обработки. Концептуально они выполняются в строгом порядке, и весь файл проходит через каждое преобразование, прежде чем начнется следующее. CPP фактически выполняет все преобразования одновременно по соображениям производительности. Эти преобразования примерно соответствуют трём «фазам перевода», описанным в стандарте C.

  1. Входной файл считывается в память и разбивается на строки.

    Разные системы используют разные соглашения для обозначения конца строки. GCC принимает ASCII управляющие последовательности LF, CR LF и CR в качестве маркеров конца строки. Это канонические последовательности, используемые Unix, DOS и VMS, а также классической Mac OS (до OSX), соответственно. Поэтому вы можете безопасно копировать исходный код, написанный в любой из этих систем, в другую и использовать его без преобразования. (GCC может потерять отслеживание текущего номера строки, если файл не использует последовательно одно соглашение, что иногда происходит, когда он редактируется на компьютерах с разными соглашениями, которые используют общую файловую систему.)

    Если последней строке любого входного файла не хватает маркера конца строки, конец файла считается, что он неявно предоставляет его. Стандарт C говорит, что это условие вызывает неопределенное поведение, поэтому GCC выведет сообщение об ошибке.

  2. Если триграфы включены, они заменяются соответствующими одиночными символами. По умолчанию GCC игнорирует триграфы, но если вы запрашиваете строгое соответствие с опцией -std или опцией -trigraphs, то он их преобразует.

    Это девять трёхсимвольных последовательностей, все начинающиеся с ‘??’, которые определены ISO C как представляющие одиночные символы. Они позволяют использовать устаревшие системы, которым не хватает некоторых знаков препинания языка C. Например, ‘??/’ означает ‘\’, поэтому '??/n' — это символьная константа новой строки.

    Триграфы не популярны, и многие компиляторы их реализуют неправильно. Переносимый код не должен полагаться на то, что триграфы будут преобразованы или проигнорированы. С опцией -Wtrigraphs GCC предоставит предупреждение, когда триграф может изменить смысл вашей программы при преобразовании. См. Wtrigraphs.

    В строковой константе вы можете предотвратить, чтобы последовательность вопросительных знаков не воспринималась как триграф, вставив обратную косую черту между вопросительными знаками или разделив строковую литерал на триграф и используя конкатенацию строковых литералов. "(??\?)" — это строка ‘(???)’, а не ‘(?]’. Традиционные компиляторы C не распознают эти конструкции.

    Девять триграфов и их замены:

    Trigraph:       ??(  ??)  ??<  ??>  ??=  ??/  ??'  ??!  ??-
    Replacement:      [    ]    {    }    #    \    ^    |    ~
  3. Строки, продолженные на следующей строке, объединяются в одну длинную строку.

    Строка, продолженная на следующей строке, — это строка, заканчивающаяся обратной косой чертой ‘\’. Обратная косая черта удаляется, а следующая строка присоединяется к текущей. Пробелы не вставляются, поэтому вы можете разделить строку в любом месте, даже посреди слова. (Обычно лучше делить строки только на пробелах.)

    Обратная косая черта в конце продолженной строки обычно называется обратная косая черта-новая строка.

    Если между обратной косой чертой и концом строки есть пробелы, это всё ещё продолженная строка. Однако, поскольку это обычно результат ошибки редактирования, и многие компиляторы не примут это как продолженную строку, GCC предупредит вас об этом.

  4. Все комментарии заменяются одним пробелом.

    Есть два вида комментариев. Блочные комментарии начинаются с ‘/*’ и продолжаются до следующего ‘*/’. Блочные комментарии не вложены:

    /* this is /* one comment */ text outside comment

    Комментарии в строке начинаются с ‘//’ и продолжаются до конца текущей строки. Комментарии в строке тоже не вложены, но это и не важно, так как они всё равно закончатся в одном и том же месте.

    // this is // one comment
    text outside comment

Безопасно вставлять комментарии в строке внутри блочных комментариев или наоборот.

/* block comment
   // contains line comment
   yet more comment
 */ outside comment

// line comment /* contains block comment */

Но будьте осторожны с выключением одного конца блочного комментария комментарием в строке.

// l.c.  /* block comment begins
   oops! this isn’t a comment anymore */

Комментарии не распознаются внутри строковых литералов. "/* blah */" — это строковая константа ‘/* blah */’, а не пустая строка.

Комментарии в строке не входят в стандарт C 1989 года, но GCC их распознаёт как расширение. В C++ и в стандарте C 1999 года они являются официальной частью языка.

Поскольку эти преобразования происходят до всех других обработок, вы можете механически разбить строку с обратной косой чертой-новой строкой в любом месте. Вы можете закомментировать конец строки. Вы можете продолжить комментарий в строке на следующую строку с обратной косой чертой-новой строкой. Вы даже можете разбить ‘/*’, ‘*/’ и ‘//’ на несколько строк с обратной косой чертой-новой строкой. Например:

/\
*
*/ # /*
*/ defi\
ne FO\
O 10\
20

эквивалентно #define FOO 1020. Все эти приёмы очень запутанны и не должны использоваться в коде, предназначенном для чтения.

Нет способа предотвратить интерпретацию обратной косой черты в конце строки как обратной косой черты-новой строки. Однако это не может повлиять на любую корректную программу.

Далее: Токенизация, Предыдущее: Наборы символов, Вверх: Обзор [Оглавление][Указатель]

© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-11.4.0/cpp/Initial-processing.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API