Директива define позволяет связать идентификатор (мы будем называть этот идентификатор замещаемой частью) с лексемой (возможно, что пустой!) или последовательностью лексем (строка символов является лексемой, заключённой в двойные кавычки), которую называют строкой замещения или замещающей частью директивы define.
Например,
#define PI 3.14159
Идентификаторы, которые используют для представления констант, называют объявленными или символическими константами. Например, последовательность символов, располагаемая после объявленной константы PI, объявляет константу 3.14159. Препроцессор заменит в оставшейся части программы все отдельно стоящие вхождения идентификатора PI на лексему, которую транслятор будет воспринимать как плавающий литерал 3.14159.
Препроцессор выполняет грубую предварительную работу по замене замещаемых идентификаторов замещающими строками. В этот момент ещё ничего не известно об именах, поскольку транслятор фактически ещё не начинал своей работы. А потому следует следить за тем, чтобы замещаемые идентификаторы входили в состав объявлений лишь как элементы инициализаторов.
Рассмотрим несколько примеров. Директива препроцессора
#define PI 3.14159
Превращает корректное объявление
float PI;
в синтаксически некорректную конструкцию
float 3.14159;
А следующее определение правильное.
float pi = PI;
После препроцессирования оно принимает такой вид:
float pi = 3.14159;
Сначала препроцессор замещает, затем транслятор транслирует. И потому здесь будет зафиксирована ошибка:
#define PI 3.14 0.00159 float pi = PI;
После препроцессирования объявление принимает такой вид:
float pi = 3.14 0.00159;
А здесь - всё корректно:
#define PI 3.14 + 0.00159 float pi = PI;
После препроцессирования получается правильное объявление с инициализацией:
float pi = 3.14 + 0.00159;
Строка замещения может оказаться пустой.
#define ZZZ
В этом случае оператор-выражение
ZZZ;
и ещё более странные конструкции
ZZZ ZZZ ZZZ ZZZ ZZZ ZZZ ZZZ ZZZ ZZZ ZZZ ZZZ;
превращаются препроцессором в пустой оператор. Это лишь побочный эффект работы препроцессора. У макроопределений с пустой строкой замещения имеется собственная область пременения.
Строка замещения может располагаться на нескольких строках. При этом символ '\' уведомляет препроцессор о необходимости включения в состав строки замещения текста, располагаемого на следующей стоке. Признаком завершения многострочного определения является символ конца строки:
#define TEXT "1234567890-=\ йцукенгшщзхъ\"
В ходе препроцессорной обработки вхождения идентификатора TEXT заменяются на строку замещения:
1234567890-= йцукенгшщзхъ\
Макроопределения define могут быть вложенными:
#include <iostream.h> #define WHISKEY "ВИСКИ с содовой." #define MARTINI "МАРТИНИ со льдом и " WHISKEY void main() {cout << MARTINI;}
В результате выполнения последнего оператора выводится строка
МАРТИНИ со льдом и ВИСКИ с содовой.
После каждого расширения препроцессор возвращается к началу файла, переходит к очередному макроопределению и повторяет процесс преобразования макроопределений. Препроцессорные замены не выполняются внутри строк, символьных констант и комментариев. При этом в замещающей части не должно быть вхождений замещаемой части макроопределения.
Так что макроопределение
#define WHISKEY "стаканчик ВИСКИ " WHISKEY
обречено на неудачу.
В макроопределениях может встречаться несколько макроопределений с одной и той же замещаемой частью. При этом следует использовать в тексте программы директиву препроцессора
#undef ИмяЗамещаемойЧасти
Эта инструкция прекращает действие препроцессора по замене соответствующего идентификатора.
#define PI 3.14 + 0.00159 float pi1 = PI; #undef PI #define PI 3.14159 float pi2 = PI;
Назад | Содержание | Вперед