1.3. Директивы препроцессораЗаголовочные файлы включаются в текст программы с помощью директивы препроцессора
#include. Директивы препроцессора начинаются со знака "диез" (#),
который должен быть самым первым символом строки. Программа, которая обрабатывает
эти директивы, называется препроцессором (в современных компиляторах
препроцессор обычно является частью самого компилятора). #include <some_file.h> #include "my_file.h" Если имя файла заключено в угловые скобки (<>), считается, что нам нужен
некий стандартный заголовочный файл, и компилятор ищет этот файл в предопределенных
местах. (Способ определения этих мест сильно различается для разных платформ
и реализаций.) Двойные кавычки означают, что заголовочный файл - пользовательский,
и его поиск начинается с того каталога, где находится исходный текст программы. #ifndef BOOKSTORE_H #define BOOKSTORE_H /* содержимое файла bookstore.h */ #endif Условная директива #ifndef проверяет, не было ли значение BOOKSTORE_H определено
ранее. (BOOKSTORE_H - это константа препроцессора; такие константы принято писать
заглавными буквами.) Препроцессор обрабатывает следующие строки вплоть до директивы
#endif. В противном случае он пропускает строки от #ifndef до # endif. #define BOOKSTORE_H определяет константу препроцессора BOOKSTORE_H. Поместив эту директиву непосредственно
после директивы #ifndef, мы можем гарантировать, что содержательная часть заголовочного
файла bookstore.h будет включена в исходный текст только один раз, сколько бы
раз ни включался в текст сам этот файл. int main() { #ifdef DEBUG cout << "Начало выполнения main()\n"; #endif string word; vector<string> text; while ( cin >> word ) { #ifdef DEBUG cout << "Прочитано слово: " << word << "\n"; #endif text.push_back(word); } // ... } Если константа DEBUG не определена, результирующий текст программы будет выглядеть так: int main() { string word; vector<string> text; while ( cin >> word ) { text.push_back(word); } // ... } В противном случае мы получим: int main() { cout << "Начало выполнения main()\n"; string word; vector<string> text; while ( cin >> word ) { cout << "Прочитано слово: " << word << "\n"; text.push_back(word); } // ... } Константа препроцессора может быть определена в командной строке при вызове компилятора с помощью опции -D (в различных реализациях эта опция может называться по-разному). Для UNIX-систем вызов компилятора с определением препроцессорной константы DEBUG выглядит следующим образом: $ CC -DDEBUG main.C Есть константы, которые автоматически определяются компилятором. Например, мы можем узнать, компилируем ли мы С++ или С программу. Для С++ программы автоматически определяется константа __cplusplus (два подчеркивания). Для стандартного С определяется __STDC__. Естественно, обе константы не могут быть определены одновременно. Пример: #idfef __cplusplus // компиляция С++ программы extern "C"; // extern "C" объясняется в главе 7 #endif int main(int,int); Другими полезными предопределенными константами (в данном случае лучше сказать переменными) препроцессора являются __LINE__ и __FILE__. Переменная __LINE__ содержит номер текущей компилируемой строки, а __FILE__ - имя компилируемого файла. Вот пример их использования: if ( element_count == 0 ) cerr << "Ошибка. Файл: " << __FILE__ << " Строка: " << __LINE__ << "element_count не может быть 0"; Две константы __DATE__ и __TIME__ содержат дату и время компиляции. #include <assert.h> assert.h - это заголовочный файл стандартной библиотеки С. Программа на C++
может ссылаться на заголовочный файл как по его имени, принятому в C, так и
по имени, принятому в C++. В стандартной библиотеке С++ этот файл носит имя
cassert. Имя заголовочного файла в библиотеке С++ отличается от имени соответствующего
файла для С отсутствием расширения .h и подставленной спереди буквой c (выше
уже упоминалось, что в заголовочных файлах для C++ расширения не употребляются,
поскольку они могут зависеть от реализации). #include <cassert> включает в текст программы содержимое файла cassert. Но поскольку все имена, используемые в стандартной библиотеке С++, определены в пространстве std, имя assert() будет невидимо до тех пор, пока мы явно не сделаем его видимым с помощью следующей using-директивы: using namespace std; Если же мы включаем в программу заголовочный файл для библиотеки С #include <assert.h> то надобность в using-директиве отпадает: имя assert() будет видно и так .
(Пространства имен используются разработчиками библиотек для предотвращения
засорения глобального пространства имен. В разделе 8.5 эта тема рассматривается
более подробно.) Содержание |
2024-10-12 15:41:16 Leonid очень информативно Оставить комментарий: |