
- •Стадии препроцессорной обработки
- •Макроопределение без параметров
- •Пример:
- •Пример:
- •Пример:
- •Цепочка подстановок
- •Сравнение макросов и функций
- •Пример:
- •Пример:
- •Пример:
- •Int II, jj, ll; // целые внешние переменные
- •Условная компиляция
- •Пример:
- •Пример:
- •Пример:
- •Вспомогательные директивы
- •Пример:
- •Void main ( ) // строка 2
- •Пример:
ЛЕКЦИЯ 24
Директивы препроцессора
Препроцессор является обязательным компонентом интегрированной среды или компилятора языка С++.
Этап препроцессорной обработки текста программы предшествует этапу компиляции. Препроцессор преобразует исходный текст программы в соответствии с содержащимися в нем директивами препроцессора, в полный текст модуля, в котором отсутствуют директивы препроцессора. Полученный текст является пригодным для компиляции.
Препроцессор может обрабатывать не только тексты программ на языке С++, а также произвольные тексты.
Стадии препроцессорной обработки
Препроцессорная обработка включает несколько последовательно выполняемых стадий (конкретная реализация может объединять несколько стадий в одну):
все системно-зависимые обозначения (например, индикатор конца строки) перекодируются в стандартные коды,
каждая пара из символов ‘\’ и “конец строки” вместе с пробелами между ними убираются, и тем самым соседние строки конкатенируются, т.е. соединяются в одну строку (далее каждая полученная таким образом строка обрабатывается препроцессором отдельно),
в каждой строке распознаются директивы и лексемы препроцессора, а каждый комментарий заменяется одним символом пустого промежутка,
выполняются директивы препроцессора и производятся макроподстановки,
escape-последовательности в символьных константах и строках (например ‘\n’ или ‘\xF2’'), заменяются соответствующими числовыми кодами,
смежные символьные константы и строки конкатенируются,
каждая препроцессорная лексема преобразуется в текст на языке С++.
К препроцессорным лексемам (лексемам препроцессора, 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 имеет несколько модификаций:
#define идентификатор строка_замещения – макроопределение без параметров
#define идентификатор(параметры) строка_замещения – макроопределение с параметрами
#define идентификатор - определение идентификатора, управляющего условной компиляцией.
Рассмотрим подробнее реализацию первых двух модификаций. Использование третьей модификации будет обсуждаться при изучении директив условной компиляции.
Замена в тексте программы одной последовательности символов на другую называется макроподстановкой. Средство ее реализации называется макросом. Для выполнения макроподстановок должны быть заданы соответствующие макроопределения. Директива #define позволяет задать макроопределения.