Си++/Препроцессорные директивы: различия между версиями
Ixpict (обсуждение | вклад) |
Ixpict (обсуждение | вклад) |
||
Строка 70: | Строка 70: | ||
===Условные директивы #if, #ifdef, #else, #endif, #elif=== |
===Условные директивы #if, #ifdef, #else, #endif, #elif=== |
||
Эти директивы позволяют подавить компиляцию части исходного файла, проверяя постоянное выражение или идентификатор. Результат проверки определяет, какие блоки текста будут переданы в компилятор и какие блоки текста будут удалены из исходного файла при предпроцессорной обработке. |
|||
====Условная компиляция==== |
====Условная компиляция==== |
||
Версия от 23:58, 18 января 2007
Препроцессор входит в любой компилятор программ на Си++ и любую среду разработки, рассчитаную на этот язык. Препроцессор обрабатывает исходный код программ до их компиляции. Препроцессорные команды, или директивы, управляют работой препроцессора.
Таких команд немного, они все начинаются со знака решётки (#
) и должны быть в начале строки исходного кода:
#define
- эта директива предусматривает определение макросов или препроцессорных идентификаторов, простейшее применение это замены в тексте программы
#include
- позволяет включать текст других файлов в текст вашей программы.
#undef
- отменяет действие директивы #define
#if
- организация условной обработки директив
#ifdef
- организация условной обработки директив
#else
- организация условной обработки директив
#endif
- организация условной обработки директив
#elif
- организация условной обработки директив
#line
- управление нумерацией строк в тексте программы
#error
- задает текст диагностического сообщения, выводящиеся при наличии ошибок
#pragma
- зависит от среды разработки
#
- нулевая, или пустая, директива, бездейственно пропускается
Директива #define
Директива #define
служит для замены часто использующихся констант, ключевых слов, операторов или выражений некоторыми идентификаторами. Идентификаторы, заменяющие текстовые или числовые константы, называют именованными константами. Идентификаторы, заменяющие фрагменты программ, называют макроопределениями, причем макроопределения могут иметь аргументы.
Основная форма синтаксиса директивы #define
:
#define идентификатор текст
Так например, в программе:
#define N 5 int main() { int a; a = N; return 0; }
Переменная а примет значение 5.
Директива #include
#include "спецификация-пути"
#include <спецификация-пути>
Директива #include добавляет содержимое заданного файла в другой файл. Можно организовать определения констант и макро в отдельном файле, а затем вставить его директивой #include в любой другой файл. Вставка файлов также очень удобна для объединения объявлений внешних переменных и сложных типов данных. Нужно определить и задать имена этих типов только один раз в созданный для этих целей файл.
Директива #include информирует предпроцессор о том, что содержание файла с заданным именем следует обрабатывать так, как будто оно присутствует в исходной программе в месте расположения этой директивы. Новый текст также может содержать директивы предпроцессора. Предпроцессор выполняет директивы в новом тексте, а затем продолжает обработку текста исходного файла.
"Спецификация пути" это имя файла, которому может предшествовать директория. Это должно быть имя существующего файла. Синтаксис спецификации файла зависит от операционной системы, в которой компилируется программа.
При поиске файлов предпроцессор использует концепцию "стандартной" директории. Расположение стандартных директорий для файлов зависит от реализации и операционной системы. Определение стандартной директории можно найти в Вашем Руководстве по компилятору.
Предпроцессор останавливает поиск сразу же после обнаружения файла с заданным именем. Если задать полную спецификацию файла, заключенную в двойные цитатные скобки (" "), то предпроцессор использует ее для поиска и игнорирует стандартную директорию.
Если заключенная в двойные цитатные скобки спецификация файла является неполной, то предпроцессор сначала ищет директорию "родительского" файла. Родительский файл это файл, содержащий директиву #include. Например, если файл f2 вставляется в файл f1, то f1 будет родительским файлом.
Вставка файлов может быть вложенной. Т.е. директива #include может появляться в файле, который сам вставляется директивой #include. Например, в приведенном выше примере файл f2 может вызывать файл f3. В этом случае f1 все еще будет родительским для f2, но "дедушкой" для f3.
При вложенной вставке файлов поиск директории начинается с родительского файла, затем проходит по дедушкиным файлам. Следовательно, поиск начинается в директории, которая содержит обрабатываемый исходный файл. Если файл не найден, то поиск продолжается в директориях, заданных в командной строке компилятора. И, наконец, производится поиск в стандартной директории.
Если спецификация файла заключена в угловые скобки, то предпроцессор не проводит поиска в текущем рабочем каталоге. Поиск файла начинается в директориях, заданный в командной строке компилятора, а затем в стандартной директории.
Допускается вложение вставки файлов до 10 уровней. При обработке вложенных #include предпроцессор всегда будет осуществлять вставку в первоначальный исходный файл.
Директива #undef
Директива #undef удаляет текущее определение идентификатора. Поэтому все встречающиеся появления идентификатора будут игнорироваться предпроцессором. Для удаления определения макро с использованием #undef, нужно задать только идентификатор макро, не задавая список параметров.
Можно применить директиву #undef к идентификатору, у которого нет определения. Тем самым пользователь получает дополнительную гарантию того, что данный идентификатор не определен.
Директива #undef обычно используется в паре с директивой #define для задания области исходной программы, в которой идентификатор имеет специальное значение. Например, некоторая функция исходной программы может иметь объявленные константы, которые задают значения среды работы, которые не влияют на остальную часть программы. Директива #undef также работает с директивой #if для управления условной компиляцией исходной программы.
Условные директивы #if, #ifdef, #else, #endif, #elif
Эти директивы позволяют подавить компиляцию части исходного файла, проверяя постоянное выражение или идентификатор. Результат проверки определяет, какие блоки текста будут переданы в компилятор и какие блоки текста будут удалены из исходного файла при предпроцессорной обработке.