Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Козак Н.В. Лекции Основы создания программ в Си...doc
Скачиваний:
24
Добавлен:
23.09.2019
Размер:
2.24 Mб
Скачать

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

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

#if выражение_1 ,

группа_операторов_1

[#elif выражение_2

группа_операторов_2 #elif выражение_3

группа рператоров_3

...]

[#else

гpyппa_onepaтopoв_else]

#endif

Первая группа операторов компилируется, если выражение_1 истинно; в противном случае операторы ее опускаются. Вторая группа компилируется, если выражение_1 ложно и выражение_2 истинно и т.д. Группа #else компилируется только в том случае, если все условные выражения ложны. Конструкция условной компиляции должна заканчиваться директивой #endif.

Разделы #elif и #else могут отсутствовать. Необходимыми элементами условной конструкции являются только директивы #if и #endif.

Операции в условиях #if

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

В директивах препроцессора имеется также одна специальная операция defined. Она позволяет проверить, определен ли некоторый символ, например:

#define TEST

#if defined(TEST)

testFile = open ("TEST.txt", O_CREAT | O_TEXT);

#else

testFile = -1;

#endif

Операция defined может комбинироваться с логическим отрицанием (!).

! defined (Sym)

будет истинным, если Sym не определен.

Директивы #ifdef и #ifndef

Эти две директивы эквивалентны соответственно #if defined и #if !defined.

Типичное применение препроцессорных директив

1. Предотвращение включения файлов

При использовании заголовков может происходить дублирование кода из-за повторного включения некоторого файла. (Допустим, у вас имеется исходный файл myprog.c, который подключает директивой #include два заголовка headerl.h и header2.h. Если, в свою очередь, оба этих файла подключают некоторый headerO.h, то последний будет дважды включен в исходный файл myprog.c. Чтобы предотвратить повторное включение кода заголовочного файла, можно организовать контроль следующим образом:

/*

** headerO.h: Заголовочный файл, который может оказаться

** многократно включенным...

*/

#ifndef __HEADER0_H

#define __HEADER0_H

/*

** Здесь идут макросы, определения типов

** и т.д. вашего заголовочного файла...

*/

#endif

Переключение разделов кода

Директивы условной компиляции могут использоваться для простого переключения между двумя различными вариантами кода — старым и экспериментальным алгоритмом, например. Это можно сделать так:

/*

** Измените определение на 0, чтобы вернуться к старому варианту.

*/

#define NEW_VER I

#if NEW_VER

/*

** Экспериментальный код.

*/

#else

/*

** Старый код.

*/

#endif

Макрос assert()

В заголовочном файле assert.h определен макрос assert (), выполняющий примерно то же самое, что и показанный выше пример. Его «прототип» можно записать как

void assert(int test);

Макрос расширяется в оператор if, проверяющий условие test. Если его значение равно 0, печатается сообщение Assertion failed: с указанием имени файла и номера строки. Вот пример:

#include <assert.h>

...

assert(!someError);

Если перед включением файла assert.h определить символ ndebug, операторы assert( ) будут «закомментированы».