Выбрать главу
Директивы #if, #elif, #else, #endif

Синтаксис:

#if <ограниченное-константное-выражение> [<текст>]

[#elif <ограниченное-константное-выражение> <текст>]

[#elif <ограниченное-константное-выражение> <текст>]

[#else <текст>]

#endif

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

Препроцессор выбирает один из участков <текста> для обработки. <Текст> может занимать более одной строки. Обычно это участок программного текста, однако это не обязательно: препроцессор можно использовать для обработки произвольного текста. Если <текст> содержит директивы препроцессора (в том числе и директивы условной компиляции), то эти директивы выполняются. Обработанный препроцессором текст передается на компиляцию.

Участок текста, не выбранный препроцессором, игнорируется на стадии препроцессорной обработки и не компилируется.

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

Если ни одно ограниченное константное выражение не истинно, то препроцессор выбирает <текст>, следующий за директивой #else. Если же директива #else отсутствует, то никакой текст не выбирается.

Ограниченное константное выражение описано в разделе 4.2.9 "Константные выражения". Такое выражение не может содержать операцию sizeof (в СП ТС — может), операцию приведения типа, константы перечисления и плавающие константы, но может содержать препроцессорную операцию defined(<идентификатор>). Эта операция дает истинное (не равное нулю) значение, если заданный <идентификатор> в данный момент определен; в противном случае выражение ложно (равно нулю). Следует помнить, что идентификатор, определенный без значения, тем не менее рассматривается как определенный. Операция defined может использоваться в сложном выражении в директиве #if неоднократно:

#if defined(mysym) || defined(yoursym)

СП TC (в отличие от СП MSC) позволяет использовать операцию sizeof в ограниченном константном выражении для препроцессора. В следующем примере в зависимости от размера указателя определяется одна из констант — либо SDATA, либо LDATA:

#if (sizeof(void *) == 2)

#define SDATA

#else

#define LDATA

#endif

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

Примеры:

/* пример 1 */

#if defined(CREDIT)

credit();

#elif defined (DEBIT)

debit();

#else

printerror();

#endif

/* пример 2 */

#if DLEVEL > 5

#define SIGNAL 1

#if STACKUSE == 1

#derine STACK 200

#else

#define STACK 100

#endif

#else

#define SIGNAL 0

#if STACKUSE == 1

#define STACK 100

#else

#define STACK 50

#endif

#endif

/* пример 3 */

#if DLEVEL == 0

#define STACK 0

#elif DLEVEL == 1

#define STACK 100

#elif DLEVEL > 5

display(debugptr);

#else

#define STACK 200

#endif

/* пример 4 */

#define REG 1 register

#define REG2 register

#if defined (M_86)

#define REG3

#define REG4

#else

#ifdefined(M_68000)

#define REG4 register

#endif

#endif

В первом примере директивы #if, #elif, #else, #endif управляют компиляцией одного из трех вызовов функции. Вызов функции credit компилируется, если определена именованная константа CREDIT. Если определена именованная константа DEBIT, то компилируется вызов функции debit. Если ни одна из .именованных констант не определена, то компилируется вызов функции printerror. Следует учитывать, что CREDIT и credit являются различными идентификаторами в языке Си.

В следующих двух примерах предполагается, что константа DLEVEL предварительно определена директивой #define.

Во втором примере показаны два вложенных набора директив #if, #else, #endif. Первый набор директив обрабатывается, если значение DLEVEL больше 5. В противном случае обрабатывается второй набор.

В третьем примере директивы уловной компиляции используют для выбора текста значение константы DLEVEL. Константа STACK определяется со значением 0, 100 или 200, в зависимости от значения DLEVEL. Если DLEVEL больше 5, то компилируется вызов функции display, а константа STACK не определяется.