Препроцесор C
Препроцесор С/С++ — програмний інструмент, який використовується в мовах програмування C та C++, препроцесор, що змінює код програми для подальшої компіляції й збірки.
Мова препроцесора C/C++ не є повною за Тюрингом хоча б тому, що за допомогою директив неможливо змусити препроцесор «зависнути».
Директиви
Директивою препроцесора називається рядок у коді, який має такий вигляд #ключове_слово параметри. Є чітко визначений список ключових слів:
define— Задає макровизначення (макроси) або константуundef— Скасовує попереднє визначенняinclude— Вставляє текст з зазначеного файлу (імпортує)if— Здійснює умовну компіляцію при істинності константного виразуifdef— Здійснює умовну компіляцію, якщо константа визначенаifndef— Здійснює умовну компіляцію при невизначеності константиelse— Гілка умовної компіляції при хибності висловлюванняelif— Гілка умовної компіляції, утворена злиттям else і ifendif— Кінець гілки умовної компіляціїline— Препроцесор змінює номер поточного рядка і ім'я файлу для компіляціїerror— Висвітлення повідомлення з зупинки компіляціїpragma— Дію, що залежить від конкретної реалізації компілятораwarning— Висвітлення повідомлення без зупинки компіляції- порожня слово — пуста дія
Опис директив
Константи і макроси #define
Константи і макроси препроцесора використовуються для визначення невеликих фрагментів коду. Зазвичай константи визначаються за допомогою великих літер.
// константа
#define BUFFER_SIZE 1024
#define PI 3.14
// макрос
#define NUMBER_OF_ARRAY_ITEMS(array) (sizeof(array)/sizeof(*(array)))
Кожна константа і кожен макрос замінюються відповідним їм визначенням. Макроси мають параметри, схожі на функції, використовуються для зменшення коду.
Приклад визначення макросу max, який приймає два аргументи: a і b та вертає більше з двох число:
#define max( a, b ) ( (a) > (b) ? (a) : (b) )
Макрос викликається як звичайна функція:
z = max(x, y);
Після заміни макроса код буде виглядати наступним чином:
z = ((x) > (y) ? (x) : (y));
Директива #include
#includeПри виявленні директив #include "..." або #include <...>, де «…» — ім'я файлу, препроцесор читає вміст зазначеного файлу, виконує директиви і заміни (підстановки).
Для #include "..."пошук файлу виконується в цій папці і папках, зазначених в командному рядку компілятора. Для #include <...> пошук файлу виконується в папках, що містять файли стандартної бібліотеки (шлях до цих папок залежать від компілятора).
Файли, що включаються зазвичай містять:
- оголошення функцій;
- оголошення глобальних змінних;
- визначення інтерфейсів;
- визначення типів даних;
- структури
- та інше.
Директива #includeзазвичай вказується на початку файлу (в заголовку), тому включаються файли називаються заголовками.
Приклад включення файлів із стандартної бібліотеки мови C:
#include <math.h> // імпортування математичних функцій(стандартна бібліотека)
#include <foo.h> // імпортування файлу не зі стандартної бібліотеки
Використання препроцесора вважається неефективним з наступних причин:
- кожен раз при включенні файлів виконуються директиви і заміни (підстановки); компілятор міг би зберігати результати препроцессірованія для використання в майбутньому;
- множинні включення одного файлу доводиться запобігати вручну за допомогою директив умовної компіляції; компілятор міг би виконувати цю задачу самостійно.
Починаючи з 1970-х років стали з'являтися способи, якими замінено включення файлів. У мовах Java і Common Lisp використовуються пакети (ключове слово package) (див. Package в Java ), в мові Паскаль — англ. units (ключові слова unitі uses), у мовах Modula, OCaml, D, Haskell і Python — модулі. Використовуються ключові слова moduleі import.
Посилання
- The C Preprocessor (англ.)