Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология Образование Политология Производство Психология Стандартизация Технологии |
Если имя файла заключено в угловые скобки, то поиск файла будет осуществляться в одном или нескольких специальных каталогах, определенных конкретной реализацией.
Если же имя файла заключено в кавычки, поиск файла выполняется, как правило, в текущем каталоге (что также определено конкретной реализацией). Во многих случаях это означает поиск текущего рабочего каталога. Если заданный файл не найден, поиск повторяется с использованием первого способа (как если бы имя файла было заключено в угловые скобки). Чтобы ознакомиться с подробностями, связанными с различной обработкой директивы #include в случае использования угловых скобок и двойных кавычек, обратитесь к руководству пользователя, прилагаемому к вашему компилятору. Инструкции #include могут быть вложенными в другие включаемые файлы. Директивы условной компиляции Существуют директивы, которые позволяют избирательно компилировать части исходного кода. Этот процесс, именуемый условной компиляцией, широко используется коммерческими фирмами по разработке программного обеспечения, которые создают и поддерживают множество различных версий одной программы. Директивы #if, #else, #elif и #endif Директивы #if, #ifdef, #ifndef, #else, #elif и #endif — это директивы условной компиляции. Главная идея состоит в том, что если выражение, стоящее после директивы #if оказывается истинным, то будет скомпилирован код, расположенный между нею и директивой #endif в противном случае данный код будет опущен. Директива #endif используется для обозначения конца блока #if. Общая форма записи директивы #if выглядит так. #if константное_выражение последовательность инструкций #endif Если константное_выражение является истинным, код, расположенный непосредственно за этой директивой, будет скомпилирован. Рассмотрим пример. // Простой пример использования директивы #if. #include < iostream> using namespace std; #define MAX 100 Int main() { #if MAX> 10 cout < < " Требуется дополнительная память"; #endif //... return 0; } При выполнении эта программа отобразит сообщение Требуется дополнительная память на экране, поскольку, как определено в программе, значение константы МАХ больше 10. Этот пример иллюстрирует важный момент: Выражение, которое стоит после директивы #if, вычисляется во время компиляции. Следовательно, оно должно содержать только идентификаторы, которые были предварительно определены, или константы. Использование же переменных здесь исключено. Поведение директивы #else во многом подобно поведению инструкции else, которая является частью языка C++: она определяет альтернативу на случай невыполнения директивы #if. Чтобы показать, как работает директива #else, воспользуемся предыдущим примером, немного его расширив. // Пример использования директив #if/#else. #include < iostream> using namespace std; #define MAX 6 Int main() { #if MAX> 10 cout < < " Требуется дополнительная память." ); #else cout < < " Достаточно имеющейся памяти."; #endif //... return 0; } В этой программе для имени МАХ определено значение, которое меньше 10, поэтому #if-ветвь кода не скомпилируется, но зато скомпилируется альтернативная #else-ветвь. В результате отобразится сообщение Достаточно имеющейся памяти.. Обратите внимание на то, что директива #else используется для индикации одновременно как конца #if-блока, так и начала #еlse-блока. В этом есть логическая необходимость, поскольку только одна директива #endif может быть связана с директивой #if. Директива #elif эквивалентна связке инструкций else-if и используется для формирования многозвенной схемы if-else-if, представляющей несколько вариантов компиляции. После директивы #elif должно стоять константное выражение. Если это выражение истинно, следующий блок кода скомпилируется, и никакие другие #elif-выражения не будут тестироваться или компилироваться. В противном случае будет проверено следующее по очереди #elif-выражение. Вот как выглядит общий формат использования директивы #elif. #if выражение последовательность инструкций #elif выражение 1 последовательность инструкций #elif выражение 2 последовательность инструкций #еlif выражение 3 последовательность инструкций //... #elif выражение N последовательность инструкций #endif Например, в этом фрагменте кода используется идентификатор COMPILED_BY, который позволяет определить, кем компилируется программа. #define JOHN 0 #define BOB 1 #define TOM 2 #define COMPILED_BY JOHN #if COMPILED_BY == JOHN char who[] = " John"; #elif COMPILED_BY == BOB char who[] = " Bob"; #else char who[] = " Tom"; #endif Директивы #if и #elif могут быть вложенными. В этом случае директива #endif, #else или #elif связывается с ближайшей директивой #if или #elif. Например, следующий фрагмент кода совершенно допустим. #if COMPILED_BY == BOB #if DEBUG == FULL int port = 198; #elif DEBUG == PARTIAL int port = 200; #endif #else cout < < " Боб должен скомпилировать код" < < " для отладки вывода данных."; #endif Директивы #ifdef и #ifndef Директивы #ifdef и #ifndef предлагают еще два варианта условной компиляции, которые можно выразить как " если определено" и " если не определено" соответственно. Общий формат использования директивы #ifdef таков. #ifdef макроимя последовательность инструкций #endif Если макроимя предварительно определено с помощью какой-нибудь директивы #define, то последовательность инструкций, расположенная между директивами #ifdef и #endif, будет скомпилирована. Общий формат использования директивы #ifndef таков. #ifndef макроимя последовательность инструкций #endif Если макроимя не определено с помощью какой-нибудь директивы #define, то последовательность инструкций, расположенная между директивами #ifdef и #endif, будет скомпилирована. Как директива #ifdef, так и директива #ifndef может иметь директиву #else или #elif. Рассмотрим пример. #include < iostream> using namespace std; #define TOM Int main() { #ifdef TOM cout < < " Программист Том."; #else cout < < " Программист неизвестен."; #endif #ifndef RALPH cout < < " Имя RALPH не определено."; #endif return 0; } При выполнении эта программа отображает следующее. Программист Том. Имя RALPH не определено. Но если бы идентификатор ТОМ был не определен, то результат выполнения этой программы выглядел бы так. Программист неизвестен. Имя RALPH не определено. И еще. Директивы #ifdef и #ifndef можно вкладывать точно так же, как и директивы #if. Директива #undef Директива #undef используется для удаления предыдущего определения некоторого макроимени. Ее общий формат таков. #undef макроимя Рассмотрим пример. #define TIMEOUT 100 #define WAIT 0 //... #undef TIMEOUT #undef WAIT Здесь имена TIMEOUT и WAIT определены до тех пор, пока не выполнится директива #undef. Основное назначение директивы #undef — разрешить локализацию макроимен для тех частей кода, в которых они нужны. Использование оператора defined Помимо директивы #ifdef существует еще один способ выяснить, определено ли в программе некоторое макроимя. Для этого можно использовать директиву #if в сочетании с оператором времени компиляции defined. Например, чтобы узнать, определено ли макроимя MYFILE, можно использовать одну из следующих команд препроцессорной обработки. #if defined MYFILE Или #ifdef MYFILE При необходимости, чтобы реверсировать условие проверки, можно предварить оператор defined символом "! " . Например, следующий фрагмент кода скомпилируется только в том случае, если макроимя DEBUG не определено. #if! defined DEBUG cout < < " Окончательная версия! "; #endif О роли препроцессора Препроцессор C++ — прямой потомок препроцессора языка С, причем без каких-либо усовершенствований. Однако его роль в C++ намного меньше роли, которую играет препроцессор в С. Дело в том, что многие задачи, выполняемые препроцессором в С, реализованы в C++ в виде элементов языка. Страуструп тем самым выразил свое намерение сделать функции препроцессора ненужными, чтобы в конце концов от него можно было бы совсем освободить язык. На данном этапе препроцессор уже частично избыточен. Например, два наиболее употребительных свойства директивы #define были заменены инструкциями C++. В частности, ее способность создавать константное значение и определять макроопределение, действующее подобно функциям, сейчас совершенно избыточна. В C++ есть более эффективные средства для выполнения этих задач. Для создания константы достаточно определить const-переменную. А с созданием встраиваемой (подставляемой) функции вполне справляется спецификатор inline. Оба эти средства лучше работают, чем соответствующие механизмы директивы #define. Приведем еще один пример замены элементов препроцессора элементами языка. Он связан с использованием однострочного комментария. Одна из причин его создания — разрешить " превращение" кода в комментарий. Как вы знаете, комментарий, использующий /*...*/-стиль, не может быть вложенным. Это означает, что фрагменты кода, содержащие /*...*/-комментарии, одним махом " превратить в комментарий" нельзя. Но это можно сделать с //-комментариями, окружив их /*...*/-символами комментария. Возможность " превращения" кода в комментарий делает использование таких директив условной компиляции, как #ifdef, частично избыточным. Директива #line Директива #line изменяет содержимое псевдопеременных _ _LINE_ _ и _ _FILE_ _. Директива #line используется для изменения содержимого псевдопеременных _ _LINE_ _ и _ _FILE_ _, которые являются зарезервированными идентификаторами (макроименами). Псевдопеременная _ _LINE_ _ содержит номер скомпилированной строки, а псевдопеременная _ _FILE_ _— имя компилируемого файла. Базовая форма записи этой команды имеет следующий вид. #line номер " имя_файла" Здесь номер — это любое положительное целое число, а имя_файла — любой допустимый идентификатор файла. Значение элемента номер становится номером текущей исходной строки, а значение элемента имя_файла— именем исходного файла. Имя_файла— элемент необязательный. Директива #line используется, главным образом, в целях отладки и в специальных приложениях. Например, следующая программа обязывает начинать счет строк с числа 200. Инструкция cout отображает номер 202, поскольку это — третья строка в программе после директивной инструкции #line 200. #include < iostream> using namespace std; #line 200 // Устанавливаем счетчик строк равным 200. Популярное:
|
Последнее изменение этой страницы: 2016-03-17; Просмотров: 1223; Нарушение авторского права страницы