Директивы
препроцессора. Указания компилятору.
Препроцессор -- собой макропроцессор, используемый для обработки исходного
файла на нулевой фазе компиляции. Компилятор Си сам вызывает препроцессор,
однако препроцессор может быть вызван автономно. Препроцессор представляет
собой инструкции, записанные в исходном коде и предназначенные для выполнения
препроц. Директива препроцессора обычно используется для облегчения модификации
исходных текстов программ и чтобы сделать их более независимыми от особенностей
различных реализаций компилятора, разных компьютеров и ос. Признаком директивы
препроцессора является символ #. Директивы могут быть записаны в любом месте
исходного файла, но их действие распространяется только от точки программы, в
которой они записаны, до конца исходного файла.
Именованные константы.
Макроопределения
Идентификаторы, представляющие собой последовательность
действий, заданной операторами и выражениями, называют макроопределениями.
Обращение к макроопределениям называют макровызовом.
Директива #define используется для замены часто используемых в программе
выражений: констант, ключевых слов, выражений осмысленными идентификаторами.
#define идентификатор_константы замещающий
текст
После появления этой строки в файле все встретившиеся далее в
тексте программы имена, совпавшие с элементом директивы:
дентификатор_константы, будут автоматически заменены на указанный в директиве
замещающий_текст прежде, чем начнется компиляция программы. Символические
константы дают возможность программисту присвоить константе имя и использовать
его далее в программе. Если возникнет необходимость изменить значение константы
во всей программе, для этого достаточно будет внести только одно изменение в
директиву препроцессора #define и перекомпилировать
программу; значение константы будет изменено по всей программе автоматически.
(#define Pi 3.14)
Операция # преобразует подставляемую
лексему в строку символов, взятую в кавычки.
Операция ## выполняет конкатенацию
(сцепление, склеивание) двух лексем. Рассмотрим следующее макроопределение:
#define TOKENCONCAT(х, у) х ## у
Когда в программе встречается макрос TOKENCONCAT, его аргументы склеиваются
и полученное выражение используется для замещения идентификатора макроса.
Например, TOKENCONCAT (О, К) будет замещаться в тексте
программы на ОК. Операция ## должна иметь два операнда.
Директива #undef
Определения символических констант и макросов могут быть
аннулированы при помощи директивы препроцессора #undef, имеющей вид: #undef идентификатор
Директива отменяет определение символической константы или макроса
с указанным идентификатором. Таким образом, область действия символической константы
или макроса начинается с места их определения и заканчивает явным их
аннулированием директивой #undef или концом файла.
Директива #include применяется для включения
копии указанного в директиве файла в то месте, где находится эта директива.
Обработка директивы #include препроцессором сводится
к тому, что директива убирается из текста и на ее место заносится копия
указанного файла. Директива #include обычно используется для
включения стандартных заголовочных файлов. Директива #include используется также при
работе с программами, состоящими из нескольких исходных файлов, которые должны
компилироваться вместе.
Условная компиляция: директивы #if, #endif, #ifdef, #ifndef, #else, #elif
Условная компиляция дает возможность программисту управлять
выполнением директив препроцессора и компиляцией программного кода. Каждая
условная директива препроцессора вычисляет значение целочисленного константного
выражения.
Условная директива препроцессора #if во многом похожа на
оператор if. Ее синтаксис имеет вид:
#if условие фрагмент
кода #endif
В этой записи условие является целочисленным выражением. Если это
выражение возвращает не нуль (истинно), то фрагмент кода, заключенный между
директивой #if и директивой #endif, компилируется. Если же
выражение возвращает нуль (ложно), то этот фрагмент игнорируется и
препроцессором, и компилятором. В условиях, помимо обычных выражений, можно
использовать конструкцию: defined. Идентификатор defined
возвращает 1, если указанный идентификатор ранее был определен директивой #define,
и возвращает 0 в противном случае. Конструкция #if defined
может быть заменена эквивалентной ей директивой #ifdef, а конструкция #if !defined
— директивой #ifndef.
Можно использовать более сложные конструкции условных директив препроцессора
при помощи директив #elif (эквивалент else if в
обычной структуре if) и #else (эквивалент else
в структуре if). Например, в коде
Директива
препроцессора #line задает целочисленное
константное начальное значение номера строки для нумерации следующих за
директивой строк исходного текста программы. Директива #line 100 задает
начальное значение номера строки, равное 100, и все последующие строки
исходного текста программы будут нумероваться, начиная с этого номера.
Директива
препроцессора #error имеет следующий
синтаксис: #error лексемы
Директива печатает сообщение об ошибке, зависящее от используемой системы
и содержащее заданные в директиве лексемы. Лексемы представляют собой группы
символов, отделяемые друг от друга пробелами.
Указания компилятору
Помимо директив препроцессора на ход компиляции оказывают
влияние указания компилятору. К ним
могут быть отнесены выражения, влияющие на размер стековой памяти. На эту
константу влияет STK_LEN. Также размер стека может быть определен с помощью
соответствующего ключа командной строки. Псевдопеременные
Каждая такая
переменная начинается и заканчивается двойными символами подчеркивания и
записывается заглавными буквами.
__LINE__содержит номер текущей строки
__FILE__имя компилируемого исходного файла
__DATE__дата начала компиляции
__TIME__время начала компиляции
|