Директива #define

#define <идентификатор> <текст>

#define <идентификатор> <список параметров> <текст>

Директива #define замінює всі входження <идентификатора> в вихідному файлі на <текст>, Наступного в директиві за <идентификатором>. Цей процес називається макропідстановки, <идентификатор> замінюється лише в тому випадку, якщо він є окремою лексему. Наприклад, якщо <идентификатор> є частиною рядка або довшого ідентифікатора, він не замінюється. якщо за <идентификатором> слід <список параметров>, то директива визначає макровизначеннями з аргументами.

<Текст> являє собою набір лексем, таких як ключові слова, константи, ідентифікатори або виразу. Один або більше пробільних символів повинні відокремлювати <текст> від <идентификатора> (Або від укладених в дужки параметрів). Якщо текст не вміщується на рядку, то він може бути продовжений на наступному рядку; для цього слід набрати в кінці рядка символ зворотний слеш і відразу за ним натиснути клавішу ENTER.

<Текст> може бути опущений. В цьому випадку всі екземпляри <идентификатора> будуть видалені з початкового тексту програми. Проте, сам <идентификатор> розглядається як певний і при перевірці директивою #if дає значення 1 (дивись розділ 7.4.1).

<Список параметров>, якщо він заданий, містить один або більше ідентифікаторів, розділених комами. Ідентифікатори в списку повинні відрізнятися один від одного. Їх область дії обмежена Макроозначення, в якому вони задані. Список повинен бути укладений в круглі дужки. Імена формальних параметрів в <тексте> відзначають позиції, в які повинні бути підставлені фактичні аргументи макровизова. Кожне ім'я формального параметра може з'явитися в <тексте> довільне число раз.

У макровизове слідом за <идентификатором> записується в круглих дужках список фактичних аргументів, відповідних формальним параметрам з <списка параметров>. <Текст> модифікується шляхом заміни кожного формального параметра на відповідний фактичний аргумент. Списки фактичних аргументів і формальних параметрів повинні містити одне і те ж число елементів.

Примітка. Не слід плутати підстановку аргументів на макроозначень з передачею аргументів функції. Підстановка в препроцесорів носить чисто текстовий характер. Ніяких обчислень або перетворень типу при цьому не проводиться.

Вище вже говорилося, що макроозначень може містити більше одного входження даного формального параметра. Якщо формальний параметр представлений виразом з побічним ефектом, то цей вислів буде обчислюватися більш ніж один раз, а разом з ним кожен раз буде виникати і побічний ефект. Результат виконання в цьому випадку може бути помилковим.

всередину <текста> в директиві #define можуть бути вкладені імена інших макроозначень або констант. Їх розширення проводиться лише при розширенні <идентификатора> цього <текста>, а не при його визначенні директивою #define. Це треба враховувати, зокрема, при взаємодії вкладених іменованих констант і макроозначень з директивою #undef. до моменту розширення містить їх тексту вони можуть вже виявитися скасовані директивою #undef.

не призведе до зациклення препроцесора.

#define WIDTH 80

#define LENGTH (WIDTH + 10)

#define FILEMESSAGE "Спроба створити файл

не вдалася через брак дискового простору "

#define REG1 register

#define REG2 register

#define MAX (x, y) ((x)> (у)). (X). (У)

#define MULT (a, b) ((a) * (b))

У першому прикладі ідентифікатор WIDTH визначається як ціла константа зі значенням 80, а ідентифікатор LENGTH - як текст (WIDTH + 10). Кожне входження ідентифікатора LENGTH в вихідний файл буде замінено на текст (WIDTH + 10), який після розширення ідентифікатора WIDTH перетвориться в вираз (80 + 10). Дужки, що оточують текст (WIDTH + 10), дозволяють уникнути помилок в операторах, подібних наступного:

Після обробки препроцесором оператор прийме вигляд:

Значення, яке присвоюється var, так само 1800. За відсутності дужок в макровизначеннями оператор мав би такий вигляд:

Значення var дорівнювало б 280, оскільки операція множення має вищий пріоритет, ніж операція додавання.

У другому прикладі визначається ідентифікатор FILEMESSAGE. Його визначення триває на другий рядок шляхом використання символу зворотний слеш безпосередньо перед натисканням клавіші ENTER.

У третьому прикладі визначено три ідентифікатора, REG1, REG2, REG3. Ідентифікатори REG1 і REG2 визначені як ключові слова register. Визначення REG3 опущено і, таким чином, будь-який входження REG3 буде видалено з вихідного файлу. У розділі 7.4.1 наведено приклад, який показує, як ці директиви можуть бути використані для завдання класу пам'яті register найбільш важливим змінним програми.

У четвертому прикладі визначається макроозначень МАХ. Кожне входження ідентифікатора МАХ в вихідному файлі замінюється на вираз ((x)> (у))? (X) :( у), в якому замість формальних параметрів х і у підставлені фактичні. Наприклад, макровиклик

заміниться на вираз

заміниться на вираз

Зверніть увагу на те, що в цьому макровизначеннями аргументи з побічними ефектами можуть привести до невірних результатів. Наприклад, макровиклик

заміниться на вираз

Операнди операції> можуть бути обчислені в будь-якому порядку, а значення змінної i залежить від порядку обчислення. Тому результат виразу непередбачуваний. Крім того, можлива ситуація, коли змінна i буде інкрементіровать двічі, що, ймовірно, не потрібно.

У п'ятому прикладі визначається макроозначень MULT. Макровиклик MULT (3,5) в тексті програми замінюється на (3) * (5). Круглі дужки, в які полягають фактичні аргументи, необхідні в тих випадках, коли аргументи макроозначення є складними виразами. Наприклад, макровиклик

заміниться на (3 + 4) * (5 + 6), що дорівнює 76. За відсутності дужок результат підстановки 3 + 4 * 5 + 6 дорівнював би 29.

Поділіться на сторінці