C для початківців
C ++ для початківців
1.3. директиви препроцесора
Заголовки включаються в текст програми за допомогою директиви препроцесора #include. Директиви препроцесора починаються зі знака "дієз" (#), який повинен бути найпершим символом рядка. Програма, яка обробляє ці директиви, називається препроцесором (в сучасних компіляторах препроцесор зазвичай є частиною самого компілятора).
Директива #include включає в програму вміст зазначеного файлу. Файл може бути зазначено двома способами:
Якщо ім'я файлу укладено в кутові дужки (<>), Вважається, що нам потрібен якийсь стандартний заголовки, і компілятор шукає цей файл в зумовлених місцях. (Спосіб визначення цих місць сильно розрізняється для різних платформ і реалізацій.) Подвійні лапки означають, що заголовки - призначений для користувача, і його пошук починається з того каталогу, де знаходиться вихідний текст програми.
Заголовки також може містити директиви #include. Тому іноді важко зрозуміти, які ж конкретно заголовки включені в даний вихідний текст, і деякі заголовки можуть виявитися включеними кілька разів. Уникнути цього дозволяють умовні директиви препроцесора. Розглянемо приклад:
Умовна директива #ifndef перевіряє, чи не було значення BOOKSTORE_H визначено раніше. (BOOKSTORE_H - це константа препроцесора, а також вони константи прийнято писати великими літерами.) Препроцесор обробляє наступні рядки аж до директиви #endif. В іншому випадку він пропускає рядки від #ifndef до # endif.
Директива
визначає константу препроцесора BOOKSTORE_H. Помістивши цю директиву безпосередньо після директиви #ifndef, ми можемо гарантувати, що змістовна частина заголовки bookstore.h буде включена у вихідний текст тільки один раз, скільки б разів не включався в текст сам цей файл.
Іншим поширеним прикладом застосування умовних директив препроцесора є включення в текст програми налагоджувальної інформації. наприклад:
Якщо константа DEBUG не визначена, результуючий текст програми буде виглядати так:
В іншому випадку ми отримаємо:
Константа препроцесора може бути визначена в командному рядку при виклику компілятора за допомогою опції -D (в різних реалізаціях ця опція може називатися по-різному). Для UNIX-систем виклик компілятора з визначенням препроцесорної константи DEBUG виглядає наступним чином:
Є константи, які автоматично визначаються компілятором. Наприклад, ми можемо дізнатися, компілюємо ми С ++ або З програму. Для С ++ програми автоматично визначається константа __cplusplus (два підкреслення). Для стандартного З визначається __STDC__. Природно, обидві константи не можуть бути визначені одночасно. приклад:
Іншими корисними зумовленими константами (в даному випадку краще сказати змінними) препроцесора є __LINE__ і __FILE__. Мінлива __LINE__ містить номер поточної компільованої рядки, а __FILE__ - ім'я компилируемого файлу. Ось приклад їх використання:
Дві константи __DATE__ і __TIME__ містять дату і час компіляції.
Стандартна бібліотека С надає корисний макрос assert (), який перевіряє деякий умова і в разі, якщо воно не виконується, видає діагностичне повідомлення і аварійно завершує програму. Ми будемо часто користуватися цим корисним макросом в наступних прикладах програм. Для його застосування слід включити в програму директиву
assert.h - це заголовки стандартної бібліотеки С. Програма на C ++ може посилатися на заголовки як по його імені, прийнятому в C, так і по імені, прийнятому в C ++. У стандартній бібліотеці С ++ цей файл носить ім'я cassert. Ім'я заголовки в бібліотеці С ++ відрізняється від імені відповідного файлу для З відсутністю розширення .h і підставленої спереду буквою c (вище вже згадувалося, що в заголовних файлах для C ++ розширення не вживаються, оскільки вони можуть залежати від реалізації).
Ефект від використання директиви препроцесора #include залежить від типу заголовки. Інструкція
включає в текст програми вміст файлу cassert. Але оскільки всі імена, які використовуються в стандартній бібліотеці С ++, визначені в просторі std, ім'я assert () буде невидимо до тих пір, поки ми явно не зробимо його видимим за допомогою наступної using-директиви:
Якщо ж ми включаємо в програму заголовки для бібліотеки З
то потреба в using директиви відпадає: ім'я assert () буде видно і так. (Простору імен використовуються розробниками бібліотек для запобігання засмічення глобального простору імен. У розділі 8.5 ця тема розглядається більш докладно.)