ТА_Методички / Lec_8
.pdfЛекція № 8
Більшість програмістів укладають в кутові дужки імена заголовних файлів, а лапки залишають для файлів, визначених користувачем. Однак щодо цього ніяких жорстких правил не передбачено. Кожен програміст може робити так, як йому зручно.
Програми на мові C + можуть використовувати директиву #include для включення нe тільки файлів, але і заголовків (headers). У мові C++ передбачений набір стандартних заголовків, які містять інформацію, необхідну для роботи різних бібліотек. Заголовок являє собою стандартний ідентифікатор, який може, але не обов’язково, бути ім'ям файлу. Таким чином, заголовок в мові C++ - це абстракція, яка гарантує, що в програму буде включена необхідна інформація.
11/29
Директиви препроцесора
Директиви умовної компіляції
Препроцесор містить кілька директив, що дозволяють вибірково компілювати окремі частини програми. Цей процес називається умовною компіляцією (conditional compilation). Він широко використовується в комерційних додатках, поcкольку дозволяє настроювати їх на конкретне оточення.
Директиви #if, #else, #elif і #endif
Ймовірно, найбільш поширеними директивами умовної компіляції є директиви #if, #else, #elif і #endif. Ці директиви дозволяють вибирати компільовані частини програми в залежності від значення константного виразу.
Директива #if має наступний загальний вигляд.
#if константний_вирз
послідовність операторів
#endif
Якщо значення константного виразу істинне, код, поміщений між директивами #if і #endif, компілюється. В іншому випадку ця частина програми ігнорується.
Директива #endif відзначає кінець блоку директиви #if.
12/29
Лекція № 8
Розглянемо приклад.
/* Простий приклад директиви # if. */ #include <stdio.h>
#define MAX 100 int main (void)
{
#if MAX> 99
printf("Компілюється, якщо розмір масиву більше 99. \ n"); #endif
return 0; }
Ця програма виводить на екран повідомлення, оскільки значення іменованої константи МАХ більше 99. Цей приклад ілюструє один дуже важливий момент. Вираз, що стоїть після директиви #if, обчислюється на етапі компіляції. Таким чином, він може містити лише раніше визначені ідентифікатори та константи, але не змінні.
Директива #else ідентична оператору else, що є частиною мови C++: вона визначає альтернативу директиві #lf.
Попередній приклад можна трохи вдосконалити.
13/29
Директиви препроцесора
/ * Simple #if / #else example. * / #include <stdio.h>
#define MAX 10 int main (void)
{
#If MAX> 99
printf ("Компілюється, якщо розмір масиву більше 99. \ n"); #else
printf ("Компілюється, якщо розмір масиву малий. \ n"); #endif
return 0;
}
У даному випадку значення іменованої константи МАХ менше 99, тому частина програми, зазначена після директиви #if, що не компілюється. Замість неї компілюється альтернатива, пов'язана з директивою #else, і на екрані з'являється повідомлення "Компілюється, якщо розмір масиву малий.".
Зверніть увагу на те, що директива #else одночасно є кінцем блоку #if і початком альтернативного блоку, оскільки директива #if може мати тільки одну альтернативу #else.
14/29
Лекція № 8
Директива #elif означає "else if" і створює ланцюжок if-else-if, дозволяючи виконувати багатоваріантну умовну компіляцію. Якщо вираз істинний, компілюється пов'язаний з ним блок коду, а інші вирази #elif не обчислюються. В іншому випадку перевіряється наступний блок. Загальний вигляд директиви #elif такий.
if вираз
послідовність операторів elif вираз 1
послідовність операторів elif вираз 2
послідовність операторів elif вираз 3
послідовність операторів elif вираз 4
. . .
elif вираз N
послідовність операторів
#endif
Наприклад, наступний фрагмент використовує значення іменованої константи "ACTIVE_COUNTRY" для визначення знаку, що позначає валюту.
15/29
Директиви препроцесора
#define US 0 #define ENGLAND 1 #define FRANCE 2
#define ACTIVE_COUNTRY US
#if ACTIVE_COUNTRY==US
char currency[] = "Долар"; #elif ACTIVE_COUNTRY == ENGLAND
char currency[] = "Фунт"; #else
char currency[] = "Євро"; #endif
Стандарт мови C встановлює, що директиви #if і #elif можуть бути вкладені, а глибина вкладення може досягати принаймні восьми рівнів. Стандарт мови C++ допускає 256 рівнів вкладення. Вкладені директиви #endif, #else або #elif зв'язуються з найближчими директивами #if або #elif. Наприклад, наступний фрагмент абсолютно вірний.
16/29
Лекція № 8
#if MAX> 100
#if SERIAL_VERSION int port = 198;
# elif
int port = 200; "\ #endif
#else
char out_buffer[100]; #endif
Директиви #ifdef і #ifndef
Інший спосіб умовної компіляції заснований на застосуванні директив
#ifdef та #ifndef, що означають "if defined" (якщо визначено) і "if not defined" (якщо не визначено). Загальний вигляд директиви #ifdef такий.
#ifdef імя_макроса послідовність операторів
#endif
Якщо ім'я макросу раніше визначено за допомогою директиви #define, компілюється відповідний блок коду.
17/29
Директиви препроцесора
Директива #ifndef має наступний загальний вигляд.
#ifndef імя_макроса послідовність операторів
#endif
Якщо ім'я макросу не було визначено за допомогою директиви #define, компілюється відповідний блок коду.
Директиви #ifdef і #ifndef можуть використовувати директиви #else і #elif. Наприклад, наступний фрагмент програми виводить на екран рядки "Привіт, Тед" і "Ральфа немає вдома". Однак, якщо іменована константа TED не визначена, на екран виводиться повідомлення "Всім привіт", а потім - "Ральфа немає вдома".
#include <stdio.h> #define TED 10
int main (void)
{
#ifdef TED printf("Привіт, Тед \ n");
18/29
Лекція № 8
#else
printf("Всім привіт \n"); #endif
#ifndef RALPH
printf("Ральфа немає вдома \n");
# endif return 0; }
Директиви #ifdef і #ifndef можуть бути вкладеними, причому стандарт мови C допускає як мінімум вісім рівнів вкладення, а стандарт мови C++ - до
256.
Директива #undef
Директива #undef видаляє визначення зазначеного імені макросу. Іншими словами, ця директива робить макрос невизначеним. Загальний вигляд директиви #undef такий.
#undef імя_макроса
19/29
Директиви препроцесора
Розглянемо, наприклад, наступний фрагмент програми.
#define LEN 100 #define WIDTH 100
char array[LEN][WIDTH]; #undef LEN
#undef WIDTH
/* У цій точці іменовані константи LEN і WIDTH не визначені */
Іменовані константи LEN і WIDTH є визначеними, поки не буде виконана директива #undef.
Оператор defined
Крім директиви #ifdef, є ще один спосіб перевірити, чи визначене ім'я макросу. Для цього можна застосовувати директиву #if в поєднанні зі статичним оператором defined, виконуваних на етапі компіляції. Оператор defined має наступний загальний вигляд.
defined імя_макросу
20/29
