Стадії і команди препроцесорної обробки

У інтегроване середовище підготовки програм на С++ в компілятор мови як обов'язковий компонент входить препроцесор. Призначення препроцесора - обробка початкового тексту програми до її компіляції.

Препроцесорна обробка відповідно до вимог стандарту мови С++ включає декілька стадій, що виконуються послідовно. Конкретна реалі-зація транслятора може об'єднувати декілька стадій, але результат пови-нен бути таким, неначебто вони виконувалися послідовно:

всі системно-залежні позначення (наприклад, системно залежний індикатор кінця рядка) перекодують в стандартні коди;

·кожна пара з символів \' і "кінець рядка" забираються, і тим самим наступний рядок початкового файлу приєднується до рядка, в якому знаходилася ця пара символів;

·у тексті розпізнаються директиви препроцесора, а кожен коментар замінюється одним символом порожнього проміжку;

·виконуються директиви препроцесора і проводяться макропідста-новки;

·ESC-послідовності в символьних константах і символьних ряд-ках, наприклад, '\ п' замінюються на їх еквіваленти (на відповідні числові коди);

·суміжні символьні рядки конкатенуються, тобто з'єднуються в один рядок.

Знайомство з перерахованими завданнями препроцесорної обробки пояснює деякі угоди синтаксису мови. Наприклад, стає зрозумілим сенс тверджень: кожен символьний рядок може бути перенесений у файлі на наступний рядок, якщо використовувати символ \' або "два символьні рядки, записані поряд, сприймається як один рядок.

Розглянемо детально стадію обробки директив препроцесора. При її виконанні можливі наступні дії:

заміна ідентифікаторів (позначень) наперед підготовленими послідовностями символів;

включення в програму текстів з вказаних файлів;

виключення з програми окремих частин її тексту (умовна компіляція);

макропідстановка, тобто заміна позначення текстом, що параметризу-ється, формованим препроцесором з урахуванням конкретних параметрів (аргументів).

Для управління препроцесором, тобто для завдання потрібних дій, використовуються команди (директиви) препроцесора, кожна з яких помі-щається на окремому рядку і починається з символу #. Визначені нас-тупні препроцесорні директиви: #define, #include, #undef, #if, #ifdef, #ifndef, #else, #endif, #elif, #line. #error, #pragma #.

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

Директива #include дозволяє включати в текст програми текст з вибраного файлу.

Директива #undef відміняє дію команди #define, яка визначила до цього ім'я препроцесорного ідентифікатора.

Директива #if і її модифікації #ifdef, #ifndef спільно з директивами #else, #endif, #elif дозволяють організувати умовну обробку тексту про-грами. Умовність полягає в тому, що компілюється не весь текст, а тільки ті його частини, які так чи інакше виділені за допомогою перерахованих дирек-тив.

Директива #line дозволяє управляти нумерацією рядків у файлі з програмою. Ім'я файлу і початковий номер рядка указуються безпосеред-ньо в директиві #line.

Директива #еггог дозволяє задати текст діагностичного повідомлення, яке виводиться при виникненні помилок.

Директива #pragma викликає дії, залежні від реалізації.

Директива # нічого не викликає, оскільки є порожньою директивою, тобто не дає ніякого ефекту і завжди ігнорується.