Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ЯП - ПОИТ (Бахтизин) часть 1 редакт.doc
Скачиваний:
2
Добавлен:
01.04.2025
Размер:
1.76 Mб
Скачать

11.3.3. Директива #undef

Определения символических констант и макросов могут быть аннулированы при помощи директивы препроцессора #undef, имеющей вид:

#undef идентификатор

Директива отменяет определение символической константы или макроса с указанным идентификатором. Таким образом, область действия символической константы или макроса начинается с места их определения и заканчивается явным их аннулированием директивой #undef или концом файла. После аннулирования соответствующий идентификатор может быть снова использован в директиве #define.

Например, возможен следующий код:

#define MyConst 128

// Здесь константа MyConst равна 128

. . .

#undef MyConst

// Здесь константу MyConst использовать нельзя

. . .

#define MyConst 64

// Здесь константа MyConst равна 64.

11.4. Условная компиляция

Условная компиляция дает возможность программисту управлять выполнением директив препроцессора и компиляцией программного кода. Каждая условная директива препроцессора вычисляет значение целочисленного константного выражения. Операции преобразования типов, операция sizeof, константы перечислимого типа и переменные не могут участвовать в выражениях, вычисляемых в директивах препроцессора, так как эти операции и иницилизация переменных происходят на этапе компиляции или выполнения программы, в то время, как обработка директив препроцессора происходит перед компиляцией. Поэтому, при условной компиляции используются операции сравнения (>, <, >=, <=, ==), операции логического И(&&), ИЛИ(||) и отрицания(!) в сочетании с константными переменными или символическими константами, определёнными с помощью директивы #define

Условная директива препроцессора #if во многом похожа на оператор if. Ее синтаксис имеет вид:

#if условие

фрагмент кода

#endif

Предупреждение: в условии могут содержаться только константные величины – либо символические константы, определённые с помощью оператора #define, либо константные переменные.

Предупреждение: между #if и #endif фигурные скобки не ставятся.

Предупреждение: не забывайте закрывать каждый #if соответствующим #endif.

В этой записи условие является целочисленным выражением. Если это выражение возвращает не нуль (истинно), то фрагмент кода, заключенный между директивой #if и директивой #endif компилируется. Если же выражение возвращает нуль (ложно), то этот фрагмент игнорируется и препроцессором, и компилятором.

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

defined идентификатор

defined возвращает 1, если ранее указанный идентификатор был определен директивой #define, и возвращает 0 в противном случае. Например, возможен следующий код:

#if defined Debug && !defined MyConst

фрагмент кода

#endif

Фрагмент кода будет выполняться, если ранее была объявлена директива

#define Debug

и не было директивы

#define MyConst

или эта директива была отменена директивой

#undef MyConst

Конструкция #if defined может быть заменена эквивалентной ей директивой #ifdef, а конструкция #if !defined – директивой #ifndef.

Например, тексты

#ifdef Size

...

#endif

и

#if defined Size

...

#endif

эквивалентны.

Оператор #if defined часто используется при включении заголовочных файлов, для исключения повторной вставки кода заголовочного файла. Например:

#if !defined(MYLIB_H)

#define MYLIB_H

/* Текст объявляемых заголовков */

#include "MyBibl.h"

...

#endif /* Конец MYLIB_H */

В первый раз, когда константа MYLIB_H ещё не объявлена !defined(MYLIB_H) возвращает 1 и операторы между #if и #endif выполняются. В том числе оператором #define MYLIB_H объявляется MYLIB_H. Поэтому при достижении препроцессором следующего вхождения этой директивы вложенное в неё содержимое будет игнорироваться.

Можно использовать более сложные конструкции условных директив препроцессора при помощи директив #elif (эквивалент else if в обычной структуре if) и #else (эквивалент else в структуре if). Например, в коде

#if условие 1

фрагмент кода 1

#elif условие 2

фрагмент кода 2

#else

фрагмент кода 3

#endif

фрагмент кода 1 будет компилироваться, если выполняется условие 1, фрагмент кода 2 будет компилироваться, если выполняется условие 2 и не выполняется условие 1, а фрагмент кода 3 будет компилироваться, если не выполняется ни одно из предыдущих условий.

Условная компиляция может быть полезна во многих случаях. Например, нередко в процессе отладки приложения в него полезно ввести различные фрагменты кода, обеспечивающие вывод отладочной информации и позволяющие следить за ходом выполнения программы. Если эти фрагменты кода используются только при отладке и не нужно, чтобы они оставались в окончательном варианте программы, то в разных местах приложения следует ввести конструкции вида

#ifdef Debug

операторы отладки

#endif

Тогда, если в начале программы вы введете директиву

#define Debug

операторы отладки будут компилироваться и выполняться. Но когда вы уберете или закомментируете эту директиву #define, определяющую введенный вами идентификатор Debug, все операторы отладки исчезнут из текста.

Конечно, можно поступить иначе: ввести переменную булева типа (переменная, которая может принимать два значения – “истина” и “ложь”. В Си такого типа не существует, однако переменную можно создать используя тип unsigned char или unsigned int и учитывать, что значение “0” и есть “0” (false), а все остальные значения подразумевают “1” (true). Этот же принцип использован в условных операторах языка Си (if; switch/case)) Debug, задать ей в начале выполнения приложения значение true и оформлять процесс отладки следующим образом:

if (Debug)

{

операторы отладки

}

Если в дальнейшем заменить задаваемое значение Debug на false, то операторы отладки перестанут выполняться. Отличие этого подхода от использования директив препроцессора заключается в том, что коды операторов отладки в этом случае останутся в тексте программы, увеличивая размер выполняемого модуля. А директивы условной компиляции просто уберут отладочный код из программы.