Справочное руководство по C++
Шрифт:
Команду препроцессора, как и любую строку, можно продолжить на следующей строке входного текста, поместив символ обратной дробной черты непосредственно перед символом конца продолжаемой строки. Препроцессор до того, как входная строка будет разбита на лексемы, удаляет символы обратной дробной черты и конца строки. Символ обратной дробной черты не должен быть последним символом входного файла.
К лексемам препроцессора относятся: лексемы самого языка (§R.2.1), имя файла, которое используется в команде #include и вообще любой символ, отличный от обобщенного пробела и несовпадающий ни с какой из лексем препроцессора.
R.16.1
По определению существует несколько фаз препроцессорной обработки. В конкретной реализации фазы могут сливаться, но результат все равно должен быть таким, как будто были выполнены все фазы.
Перечислим их.
При необходимости символы, зависящие от системы символы, обозначающие конец строки, заменяются на стандартный символ конца строки. Аналогичной замене подлежат все зависящие от системы символы. Определенные последовательности символов (триграфы) заменяются на эквивалентный им отдельный символ (§R.16.2).
Удаляются все такие пары символов: обратная дробная черта, следующий за ней символ конца строки. В результате будут слиты строки входного текста, из которых была удалена эта пара.
Входной текст разбивается на лексемы препроцессора и последовательность обобщенных пробелов. Каждый комментарий заменяется на один пробел. Входной текст не должен кончаться посреди лексемы или комментария.
Выполняются команды препроцессора, и производятся макроподстановки (§R.16.3, §R.16.4, §R.16.5, §R.16.6, §R.16.7 и §R.16.8).
В символьных константах и строках литералов комбинации специальных символов заменяются на свои эквиваленты (§R.2.5.2).
Сливаются соседние строки литералов.
Результат препроцессорной обработки подвергается синтаксическому и семантическому анализу, транслируется, а затем связывается с необходимыми библиотеками и другими программами.
R.16.2 Триграфные последовательности
Прежде чем начнется какая-либо иная препроцессорная обработка, каждое вхождение триграфной последовательности заменяется на один символ в соответствии с приведенной ниже таблицей.
??= | # |
??/ | \ |
??' | ^ |
??( | [ |
??) | [ |
??! | | |
Например, строка
преобразуется в
R.16.3 Макроопределение и макроподстановка
Команда вида
называется макроопределением. Она указывает препроцессору, что надо произвести замену всех последующих вхождений идентификатора на заданную последовательность лексем, называемую строкой замены. Обобщенные
описание
после макроподстановки примет вид
Определенный таким способом идентификатор можно переопределить с помощью другой команды #define, но при условии, что строки замены в обоих определениях совпадают. Все символы обобщенного пробела, разделяющие лексемы, считаются идентичными.
Команда вида
называется макроопределением с параметрами или "функциональным" макроопределением. В нем недопустимы пробелы между первым идентификатором и символом (. Определенный таким способом идентификатор можно переопределить с помощью другого функционального макроопределения, но при условии, что во втором определении то же число и те же наименования параметров, что и в первом, а обе строки замены совпадают. Все символы обобщенного пробела, разделяющие лексемы, считаются идентичными.
Последующие вхождения идентификатора, определенного в функциональном макроопределении, если за ним следуют символ (, последовательность лексем, разделенных запятыми, и символ ), заменяются на строку лексем из макроопределения. Обобщенные пробелы, окружающие строку замены, отбрасываются. Каждое вхождение идентификатора, из списка параметров макроопределения, заменяется на последовательность лексем, представляющую соответствующий фактический параметр в макровызове. Фактическими параметрами являются строки лексем, разделенные запятыми. Запятая, взятая в кавычки, или находящаяся в символьной константе или во вложенных круглых скобках, не разделяет параметров. Число фактических параметров макровызова должно совпадать с числом параметров макроопределения.
После идентификации параметров для функционального макроопределения происходит подстановка фактических параметров. После выполнения подстановок в параметре (если они были) этот параметр в строке замены замещается фактическим параметром из макровызова (§R.16.3.3); исключения составляют случаи, когда параметру предшествует лексема # (§R.16.3.1), или с ним соседствует лексема ## (§R.16.3.2).
Приведем пример. Пусть есть макроопределения
Тогда макровызов
после подстановки примет вид
Для обоих видов макроопределений строка замены проверяется на наличие других макроопределений (§R.16.3.3).
R.16.3.1 Операция #
Если непосредственно перед параметром в строке замены идет лексема #, то при подстановке параметр и операция # будут заменены на строку литералов, содержащую имя соответствующего параметра макровызова. В символьной константе или строке литералов, входящих в параметр, перед каждым вхождением \ или " вставляется символ \.