Условные директивы
Условная компиляция
Включение текстов из файлов
Для включения текста из файла используется команда #include, имеющая три формы записи:
#include < имя_файла > /* Имя в угловых скобках */
#include "имя_файла" /* Имя в кавычках */
#include имя_макроса
/* Макрос, расширяемыи до обозначения файла*/
где имя_макроса - это введенный директивой #define препроцессорный идентификатор либо макрос, при замене которого после конечного числа подстановок будет получена последовательность символов <имя_файла> либо "имя_файла".
До сих пор мы в программах и примерах фрагментов программ использовали только первую форму команды #include. Существует правило, что если имя_файла - в угловых скобках, то препроцессор разыскивает файл в стандартных системных каталогах. Если имя_файла заключено в кавычки, то вначале препроцессор просматривает текущий каталог пользователя и только затем обращается к просмотру стандартных системных каталогов.
Директивы ветвлений. Условная компиляция обеспечивается в языке Си следующим набором директив, которые, не точно соответствуя названию, управляют не компиляцией, а препроцессорной обработкой текста:
#if целочисленное_константное_выражение
#ifdef идентификатор
#ifndef идентификатор
#else
#endif
#elif
Первые три директивы выполняют проверку условии, две следующие - позволяют определить диапазон действия проверяемого условия. (Директиву #elif рассмотрим несколько позже.) Общая структура применения директив условной компиляции такова:
#if...
текст_1
#else
текст_2
#endif
Конструкция #else текст_2 необязательна. Текст_1 включается в компилируемый текст только при истинности проверяемого условия (обозначено многоточием после #if). Если условие ложно, то при наличии директивы #else на компиляцию передается текст 2.
#if целочисленное_константное_выражение
Здесь проверяется значение константного выражения, в которое могут входить целые константы и идентификаторы. Идентификаторы могут быть определены на препроцессорном уровне, и тогда их значение определяется подстановками. В противном случае считается, что идентификаторы имеют нулевые значения. Если константное выражение отлично от нуля, то считается, что проверяемое условие истинно.
#ifdef идентификатор
Проверяется, определен ли с помощью директивы #define к текущему моменту идентификатор, помещенный после #ifdef. Если идентификатор определен, т.е. является препроцессорным, то текст 1 используется компилятором.
#ifndef идентификатор
Проверяется обратное условие - истинным считается неопределенность идентификатора, т.е. тот случай, когда идентификатор те был использован в команде #define или его определение было отменено командой #undef.
Для организации мультиветвлений во время обработки препроцессором исходного текста программы введена директива
#elif целочисленное_константное_выражение
Структура исходного текста с применением этой директивы #elif:
#if условие текст_для_if
#elif выражение_1 текст_1
#elif выражение_2 текст_2
#elif выражение_3
текст_3
...
#else
текст_для_случая_else
#endif
Препроцессор проверяет вначале условие в директиве #if. Если оно ложно (равно 0), - вычисляется выражение_1, если при этом оказывается, что и значением выражения_1 также равно 0, - вычисляется выражение_2, и т.д.
Таким образом, препроцессор обрабатывает всегда только один из участков текста, выделенных директивами условной компиляции.