ТА_Методички / Lec_8
.pdfЛекція № 8
Якщо в даний момент ім'я макросу є визначеним, вираз має значення істини. В іншому випадку він хибний. Наприклад, щоб розпізнати, чи є іменована константа MYFILE визначеною, можна використовувати одну з наступних команд препроцесора:
#if defined MYFILE
або
#ifdef MYFILE
Поставивши перед оператором defined символ !, можна задати протилежну умова. Наприклад, наступний фрагмент програми компілюється тільки в тому випадку, якщо іменована константа DEBUG не визначена.
#if ! defined DEBUG printf("Final version! \n");
#endif
Одна з причин, по якій використовується оператор defined, полягає в тому, що він дозволяє перевірити, чи визначене ім'я макросу за допомогою оператора
#elif.
21/29
Директиви препроцесора
Директива #line
Директива #line відповідно змінює вміст макросів _ _LINE_ _ і _ _FILE_ _, що представляють собою ідентифікатори, визначені компілятором. Ідентифікатор _ _LINE_ _ містить номер поточного рядка коду, що компілюється. Ідентифікатор _ _FILE_ _ являє собою рядок, що містить ім'я файлу, що компілюється.
Загальний вигляд директиви #line такий.
#line номер "ім'я файлу"
Тут параметр номер дорівнює кожному позитивному числу, яке стає новим значенням макросу _ _LINE_ _. Параметр ім'я файлу не обов'язковий і може бути будь-яким допустимим ім'ям файлу, яке стає новим значенням макросу _ _FILE_ _. Директива #line в основному використовується при налагодженні програм; в спеціальних додатках.
Наприклад, наступний код встановлює, що нумерацію рядків слід починати з числа 100. Функція printf() виводить на екран число 102, оскільки вона знаходиться в третьому рядку програми, відраховуючи від директиви #line 100.
22/29
Лекція № 8
#include <stdio.h> |
|
#line 100 |
/ * Встановлює лічильник рядків * / |
int main (void) |
/ * Рядок 100 * / |
{ |
/ * Рядок 101 * / |
printf("%d \n", LINE) |
/ * Рядок 102 * / |
return 0; } |
|
Директива #pragma
Директива #pragma залежить від реалізації. Вона дозволяє передавати компілятору різні команди. Наприклад, компілятор може мати опцію, яка передбачає трасування виконання програми. Цю опцію можна задати за допомогою директиви #pragma. Деталі й допустимі опції перераховуються до документації, що супроводжує компілятор.
Оператори препроцесора # і ##
Препроцесор має два оператора: # і ##. Ці оператори використовуються в директиві #define. Оператор #, який називається оператором перетворення в рядок (stringize), перетворює свій аргумент в рядок, поміщений в лапки. Як приклад розглянемо наступну програму.
23/29
Директиви препроцесора
#include <stdio.h> #define mkstr (s) # s int main (void)
{
printf (mkstr (Я люблю C++)); return 0; }
Препроцесор перетворить рядок printf(mkstr (Я люблю C++));
в рядок
printf ("Я люблю C++");
Оператор ##, званий оператором конкатенації (pasting), "склеює" дві лексеми.
#include <stdio.h>
#define concat (a, b) a ## b int main (void) {
int xy = 10;
printf("%d", concat(x, у)); return 0; }
24/29
Лекція № 8
Препроцесор перетворить рядок
printf("%d", concat(x, у));
в рядок
printf("%d", xy);
Якщо ці оператори здалися вам дивними, згадайте, що в більшості випадків без них можна спокійно обійтися. В основному вони призначені для обробки деяких особливих ситуацій.
Імена наперед визначених (predefined) макросів
У мові C++ існує шість вбудованих імен макросів:
_ _LINE_ _
_ _FILE_ _
_ _DATE_ _
_ _ TIME_ _
_ _STDC_ _
_ _ cplusplus_ _
Перші п'ять із цих макросів відносяться до мови С.
25/29
Директиви препроцесора
Макроси _ _LINE_ _ і _ _FILE_ _ вже обговорювалися в розділі, присвяченому директиві #line. Коротко кажучи, вони містять номер поточного рядка та ім'я файлу, який компілюється.
Макрос _ _DATE_ _ містить рядок, що має вигляд місяць/день/рік. У нього записується дата компіляції файлу.
Макрос _ _TIME_ _ містить час компіляції програми, представлений уформаті години:хвилини:секунди.
Сенс макросу _ _STDC_ _ залежить від реалізації. Як правило, якщо макрос _ _STDC_ _ визначений, компілятор суворо дотримується стандарту мов С, C++, не допускаючи ніяких нестандартних розширень.
Коментарі
Стандарт С89 допускає лише один вид коментарів, що починаються символами /* і закінчуються символами */. Між зірочкою і косою рискою не повинно бути пробілів. Компілятор ігнорує текст, що міститься всередині коментарів. Наприклад, наступна програма виведе на екран слово "Привіт".
26/29
Лекція № 8
#include <stdio.h> int main (void)
{
printf("Привіт");
/* printf ("Тут"); */. return 0;}
Цей стиль коментарів називається багаторядковим (multiline comment), оскільки такі коментарі можуть складатися з декількох рядків.
/ * Це - приклад багатострічкового коментару * /
Коментарі можна розміщувати в будь-якому місці програми, з одним винятком вони не можуть розривати ключові слова або ідентифікатори. Наприклад, наступний коментар цілком коректний.
х = 10 + /* Додаємо число */ 5;
У той же час коментар
swi / * Це абсолютно неправильно * / tch {...
27/29
Директиви препроцесора
є невірним, оскільки ключове слово не може містити коментар. Втім, коментарі не слід вставляти в середину виразів, бо це лише заплутуючи програму.
Багаторядкові коментарі не можуть бути вкладеними. Інакше кажучи, один коментар не може містити інший. Наприклад, наступний фрагмент коду викличе помилку компіляції.
/* Це зовнішній коментар
х = у/а; / * Це внутрішній коментар - він породжує помилку * / */
Однорядкові коментарі
Мова C++ (і стандарт С99) передбачає два види коментарів. По-перше, багатострічкові коментарі. По-друге; однорядкові коментарі (single-line comments).
// Це - однорядковий коментар.
28/29
Лекція № 8
Однорядкові коментарі особливо корисні для створення коротких покрокових описів програми. Незважаючи на те що вони не підтримуються стандартом С89, багато компілятори мови С дозволяють їх застосовувати. Крім того, вони були включені в стандарт С99.
І останнє: однорядкові коментарі можна вкладати в багаторядкові. Коментарі слід розміщувати там, де необхідні пояснення. Наприклад, всі функції, за винятком дуже коротких і самоочевидних, повинні містити коментарі, в яких описано їх призначення, спосіб виклику і повертається значення.
29/29
