Читать «QT 4: программирование GUI на С++» онлайн - страница 331

Жасмин Бланшет

Препроцессор

Препроцессор С++ — это программа, которая обрабатывает исходный файл .cpp, содержащий директивы # (такие, как #include, #ifndef и #endif), и преобразует его файл исходного кода, который не содержит таких директив. Эти директивы предназначены для выполнения простых операций с текстом исходного файла, например для выполнения условной компиляции, включения файла и разворачивания макроса. Обычно препроцессор автоматически вызывается компилятором, однако в большинстве систем предусмотрена возможность непосредственного его вызова (часто для этого используется опция компилятора —E и /E).

• Директива #include разворачивается в содержимое файла, имя которого указывается в угловых скобках (< >) или в двойных кавычках (" "), в зависимости от расположения заголовочного файла в стандартном каталоге или в каталоге текущего проекта. Имя файла может содержать .. и / (этот символ правильно интерпретируется компиляторами Windows как разделитель каталогов). Например:

#include "../shared/globaldefs.h"

• С помощью директивы #define определяется макрос. Каждое появление в тексте программы имени, расположенном после директивы #define, заменяется определенным для него значением. Например, директива

#define PI 3.14159265359

указывает препроцессору на необходимость замены каждого появления в текущей единице компиляции лексемы PI лексемой 3.14159265359. Для предотвращения конфликтов имен с переменными и классами общей практикой стало назначение макросам имен, состоящих только из прописных букв. Можно определять макрос с аргументами:

#define SQUARE(x) ((x) * (x))

Считается хорошим стилем окружение в теле макроса скобками любых параметров, а также всего тела макроса, что позволяет избегать проблем, связанных с приоритетностью операторов. В конце концов нам нужно, чтобы запись 7 * SQUARE(2 + 3) разворачивалась в 7 * ((2 + 3) * (2 + З)), а не в 7 * 2 + 3 * 2 + 3.

Компиляторы С++ обычно позволяют определять макросы в командной строке, используя опцию —D или /D. Например:

CC -DPI=3.14159265359 -с main.cpp

Макросы были очень популярны в прежние дни, когда еще не были введены typedef, перечисления, константы, встраиваемые функции и шаблоны. В наши дни они играют важную роль в предотвращении многократных включений заголовочных файлов.

• Макрос можно отменить в любом месте с помощью директивы #undef:

#undef PI

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

• Отдельные фрагменты программного кода можно обрабатывать или пропускать при помощи директив #if, #elif, #else и #endif в зависимости от конкретных числовых значений макросов. Например:

#define NO_OPTIM 0

#define OPTIM_FOR_SPEED 1

#define OPTIM_FOR_MEMORY 2

#define OPTIMIZATION OPTIM_FOR_MEMORY

#if OPTIMIZATION == OPTIM_FOR_SPEED

typedef int MyInt;

#elif OPTIMIZATION == OPTIM_FOR_MEMORY

typedef short MyInt;