Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Директивы препроцессора.doc
Скачиваний:
7
Добавлен:
20.07.2019
Размер:
206.34 Кб
Скачать

ЛЕКЦИЯ 24

Директивы препроцессора

Препроцессор является обязательным компонентом интегрированной среды или компилятора языка С++.

Этап препроцессорной обработки текста программы предшествует этапу компиляции. Препроцессор преобразует исходный текст программы в соответствии с содержащимися в нем директивами препроцессора, в полный текст модуля, в котором отсутствуют директивы препроцессора. Полученный текст является пригодным для компиляции.

Препроцессор может обрабатывать не только тексты программ на языке С++, а также произвольные тексты.

Стадии препроцессорной обработки

Препроцессорная обработка включает несколько последовательно выполняемых стадий (конкретная реализация может объединять несколько стадий в одну):

  1. все системно-зависимые обозначения (например, индикатор конца строки) перекодируются в стандартные коды,

  2. каждая пара из символов ‘\’ и “конец строки” вместе с пробелами между ними убираются, и тем самым соседние строки конкатенируются, т.е. соединяются в одну строку (далее каждая полученная таким образом строка обрабатывается препроцессором отдельно),

  3. в каждой строке распознаются директивы и лексемы препроцессора, а каждый комментарий заменяется одним символом пустого промежутка,

  4. выполняются директивы препроцессора и производятся макроподстановки,

  5. escape-последовательности в символьных константах и строках (например ‘\n’ или ‘\xF2’'), заменяются соответствующими числовыми кодами,

  6. смежные символьные константы и строки кон­катенируются,

  7. каждая препроцессорная лексема преобразуется в текст на языке С++.

К препроцессорным лексемам (лексемам препроцессора, preprocessing token) относятся

  • символьные константы,

  • строковые константы,

  • имена заголовочных файлов,

  • идентификаторы,

  • знаки операций,

  • препроцессорные числа,

  • знаки препинания,

  • другие символы, отличные от пробела.

На стадии обработки директив препроцессора в зависимости от типа директивы могут выполняться следующие действия:

  • замена идентификаторов определенной последовательностью символов,

  • включение в программу текстов из заголовочных файлов,

  • исключение из программы отдельных частей ее текста (условная компиляция),

  • макроподстановка, т.е. замена обозначения параметризованным текстом, формируемым препроцессором с учетом конкретных параметров.

Директивы препроцессора

Для управления препроцессорной обработкой (для задания нужных действий), используются директивы (команды) препроцессора.

Обобщенный формат директивы препроцессора:

#имя_директивы лексемы_препроцессора

Каждая директива должна располагаться в отдельной строке. До и после символа ‘#’, до, после и между лексема­ми препроцессора могут содержаться пробелы.

Окончанием препроцессорной директивы служит конец текстовой строки, при наличии символа ‘\’, обозначающего перенос строки - конец следую­щей строки текста.

Определены следующие препроцессорные директивы: #define, #undef , #include, #if, #ifdef, #ifndef , #else, #endif, #elif, #line, #error, #pragma, #.

Директива #define позволяет осуществлять макроподстановки – замены в тексте программы одной последовательности символов на другую. С помощью данной директивы также определяются символические константы, управляющие условной компиляцией, и используемые директивами #ifdef и #ifndef.

Директива #undef отменяет действие директивы #define.

Директива #include позволяет включать в текст программы текст из указанного файла.

Директивы #if, #ifdef, #ifndef, #else, #endif, #elif называют директивами условной компиляции. Они позволяют организовать услов­ную (в зависимости от результата выполнения некоторого условия) препроцессорную обработку текста программы. Таким образом, из последующего процесса компиляции можно исключить часть текста программы.

Директива #if задает проверку условия-выражения, директива #ifdef - проверку определенности идентификатора, #ifndef - проверка неопределенности идентификатора.

Директива #else определяет начало альтернативной ветви для директив #if, #ifdef, #ifndef, директива #endif – их окончание.

Директива #elif является составной директивой #else/#if.

Директива #line позволяет управлять нумерацией строк в файле с программой, а также изменять имя файла.

Директива #error задает текст сообщения, которое выводится при возникновении ошибок компиляции.

Директива #pragma вызывает действия, зависящие от конкретной реализации компилятора.

Директива # (пустая директива) ни выполняет никаких действий и всегда игнорируется.

Кроме препроцессорных директив имеются три препроцессорные операции Совместно с директивой #define:

  • defined - проверка истинности операнда,

  • ## - конкатенация препроцессорных лексем,

  • # - преобразование операнда в строку символов (заключение в кавычки).

Директива #define имеет несколько модификаций:

  1. #define идентификатор строка_замещения – макроопределение без параметров

  2. #define идентификатор(параметры) строка_замещения – макроопределение с параметрами

  3. #define идентификатор - определение идентификатора, управляющего условной компиляцией.

Рассмотрим подробнее реализацию первых двух модификаций. Использование третьей модификации будет обсуждаться при изучении директив условной компиляции.

Замена в тексте программы одной последовательности символов на другую называется макроподстановкой. Средство ее реализации называется макросом. Для выполнения макроподстановок должны быть заданы соответствующие макроопределения. Директива #define позволяет задать макроопределения.