Лекция: Директиви препроцесора

Існує 14 стандартних директив препроцесора:

 

#include

#define

#undef

#if

#ifdef

#ifndef

#elif

#else

#endif

#error

#import

#line

#pragma

#using

 

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

Правильно підбираючи та використовуючи директиви, особливо директиву #define, на мові C++ можна писати дуже ефективності програми, які по швидкості виконання і по використовуваній оперативній пам'яті не будуть поступатися добре написаних програм на машино — орієнтованих мовах програмування типу Асемблера.

Потрібно пам'ятати, що препроцесор, який обробляє директиви, працює з рядками символів і практично нічого не знає про синтаксис, змінні, типи даних, оператори, інструкції та області видимості мови C++. Компілятор має справу вже з текстом програми, повністю обробленим препроцесором, і тому помилки макропрограмування, що привели до помилок у програмі на мові C++, можуть діагностуватися вже під час компіляції. Це в значній мірі ускладнює розробку і перевірку програм з макрозасобами. Така ціна ефективності програм, яку, як правило, іншими засобами досягти не можна.

6.2 Директива #define

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

Ідентифікатори, що замінюють текстові або числові літерали, називають іменованими літералами.

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

6.2.1 Іменовані літерали

Формат директиви препроцесора #define, яка оголошує іменований літерал, наступний:

 

#define ідентифікатор літерал

 

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

 

#define PI 3.14159

всі подальші входження в текст програми іменованого літерала PI будуть замінені на чисельний літерал 3.14159.

Директива дає можливість програмісту присвоїти літералу ім'я і використовувати його далі в програмі замість літерала. Якщо виникне необхідність змінити значення літерала у всій програмі, для цього досить буде внести тільки одну зміну в директиву препроцесора #define і перекомпілювати програму; значення літерала буде змінено в усій програмі автоматично.

Відзначимо, що в директиві все, що знаходиться праворуч від ідентифікатора, є текстом, що заміщає цей ідентифікатор. Наприклад, після виконання директиви:

 

#define PI =3.14159

 

препроцесор замінить всі імена PI на текст =3.14159. Багато логічних і синтаксичних помилок виникають внаслідок нерозуміння цього правила.

Повторне оголошення значення іменованого літерала також є типовим джерелом помилок.

Слід відмітити, що в мові C++ віддається перевага використанню іменованих змінних типу const, а не іменованих літералів. Константні змінні є даними визначеного типу, і їх імена видно налагоджувачу. А якщо використовується іменований літерал, то після того, як ідентифікатор був замінений на відповідний текст, тільки цей текст і буде видно налагоджувачу.

Недоліком змінних типу const є те, що для зберігання свого значення їм потрібна пам'ять в об'ємі, відповідному їх типу, тоді як для іменованих літералів не вимагається ніякої додаткової пам'яті.

Використання ясних за сенсом ідентифікаторів для іменованих літералів покращує розуміння тексту програми, робить текст самодокументованим.

еще рефераты
Еще работы по информатике