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

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

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

#if постоянное_выражение

блок_текста

[#elif постоянное_выражение

блок_текста]

[#elif постоянное_выражение

блок_текста]

[#else

блок_текста]

#endif

Примечание: содержимое в квадратных скобках может отсутствовать.

Препроцессор выбирает одно из заданных появлений блок_текста для дальнейшей обработки, который может быть любой последовательностью текста. Он может занимать несколько строк. Обычно блок_текста – это текст программы, который имеет значение для компилятора или препроцессора. Препроцессор обрабатывает выбранный блок_текста и передает его компилятору. Если блок_текста содержит директивы препроцессора, то препроцессор выполнит эти директивы. Все блоки текста, не выбранные препроцессором, удаляются из обрабатываемого файла. Следовательно, эти блоки текста не компилируются.

Препроцессор выбирает отдельный блок_текста в зависимости от постояного_выражения, которое следует за каждой директивой #if или #elif, пока результатом его не будет "истина" (не ноль). Выбирается весь текст (включая начинающиеся с # другие директивы препроцессора) до #elif, #else или #endif. Если значением всех постоянных_выражений будет "ложь", или нет директивы #elif, то препроцессор выберет блок текста после предложения #else. Если предложения #else нет, то блок вообще не выбирается.

Постоянное_выражение не может содержать выражений sizeof(), приведения типа или перечислимых констант. Однако, они могут содержать оператор препроцессора defined в специальном постоянном выражении, имеющем следующий синтаксис:

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

Это постоянное_выражение будет иметь значение "истина" (не ноль), если заданный идентификатор определен, в противном случае будет иметь значение "ложь" (ноль). Идентификатор, определенный как пустой текст, считается определенным. Например:

#if defined(MODUL1)  

modul1();  

#elif defined(MODUL2)  

modul2();  

#else  

printerror();  

 #endif  

В этом примере директивы #if и #endif управляют компиляцией одного из трех вызовов функции. Вызов функции modul1() компилируется, если определен идентификатор MODUL1. Если определен идентификатор MODUL2, то компилируется вызов функции modul2(). Если не определен ни один из идентификаторов, то компилируется вызов printerror().

Примечание: MODUL1 и modul1 – это разные идентификаторы в языке С/С++.

Директива

#if defined(mysym)

это то же, что и директива

#ifdef mysym

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

#if defined(mysym) && !defined(yoursym)

Директивы #if, #elif, #else и #endif могут быть вложены в другие директивы #if. Каждая вложенная директива #else, #elif или #endif принадлежит к ближайшей к ней директиве #if. Следующий пример иллюстрирует два вложенных набора директив #if, #else и #endif:

#if LEVEL>5  

#define SIGNAL 1  

#if STACKUSE == 1  

#define STACK 200  

#else  

#define STACK 100  

#endif  

#else  

#define SIGNAL 0  

#if STACKUSE == 1  

#define STACK 100  

#else  

#define STACK 50  

#endif  

#endif  

Первый набор директив будет обработан только, если значение LEVEL>5 – "истина". В противном случае будет обработан второй набор директив.