Добавил:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
2
Добавлен:
31.01.2021
Размер:
27.67 Кб
Скачать

Інформатика — Теорія — Синтаксис директив препроцесора    Автори

|

Контакти

|

Підсистема допомоги

|

Методичні вказівки

|

Анотація

|

Назад

   ІнформатикаДирективи препроцесора : Синтаксис директив препроцесораЗміст курсу

Вступ

Теорія

Синтаксис директив препроцесора

Практика

Практичне заняття

Лабораторна робота

Поточна перевірка знань

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

Версія для друку

  Синтаксис директив препроцесора Директива #include      Синтаксис :#include "ім'я_файла"#include <ім'я_файла>.     Директива #include використовується для включення копії вказаного файла в те місце програми, де знаходиться ця директива.      Різниця між двома формами директиви полягає в методі пошуку препроцесором файла, що включається. Якщо ім'я файла розміщене в "кутових" дужках < >, то послідовність пошуку препроцесором заданого файла в каталогах визначається встановленими каталогами включення (include directories). Якщо ж ім'я файла заключне в лапки, то препроцесор шукає в першу чергу файл у поточній директорії, а потім вже у каталогах включення.     Робота директиви #include зводиться практично до того, що директива #include прибирається, а на її місце заноситься копія вказаного файла.     Текст файла, що включається може містити директиви препроцессора, і директиву #include зокрема. Це означає, що директива #include може бути вкладеною. Допустимий рівень вкладеності директиви #include залежить від конкретної реалізації компілятора. #include <stdio.h>     /* приклад 1*/#include "defs.h"      /* приклад 2*/     В першому прикладі у головний файл включається файл з ім'ям stdio.h. Кутові дужки повідомляють компілятору, що пошук файла необхідно здійснювати в директоріях, вказаних в командному рядку компіляції, а потім в стандартних директоріях.     В другому прикладі в головний файл включається файл з ім'ям defs.h. Подвійні лапки означають, що при пошуку файла спочатку повинна бути переглянута директорія, що містить поточний файл.      В С++ є також можливість задавати ім'я шляху в директиві #include за допомогою іменованої константи. Якщо за словом include слідує ідентифікатор, то препроцесор перевіряє, чи не іменує він константу або макровизначення. Якщо ж за словом include слідує рядок, що заключений в лапки або в кутові дужки, то rjvgskznjh не буде шукати в ній ім'я константи.#define myincl "c:\test\my.h"

#include myincl

Директива #define      Синтаксис :#define ідентифікатор текст#define ідентифікатор (список_параметрів) текст.     Директива #define заміняє всі входження ідентифікатора у програмі на текст, що слідує в директиві за ідентифікатором. Цей процес називається макропідстановкою.

     Ідентифікатор замінюється лише в тому випадку, якщо він представляє собою окрему лексему. Наприклад, якщо ідентифікатор є частиною рядка або більш довгого ідентифікатора, він не замінюється. Якщо за ідентифікатором слідує список параметрів, то директива визначає макровизначення з параметрами.     Текст представляє собою набір лексем, таких як ключові слова, константи, ідентифікатори або вирази. Один або більше пробільних символів повинні відділяти текст від ідентифікатора (або заключених в дужки параметрів). Якщо текст не вміщується в рядку, то він може бути продовжений на наступному рядку; для цього слід набрати в кінці рядка символ "обернений слеш" \ і зразу за ним натиснути клавішу Enter. Текст може бути опущений. В такому разі всі екземпляри ідентифікатора будуть вилучені з тексту програми. Але сам ідентифікатор розглядається як визначений і при перевірці директива #if дає значення 1.     Список параметрів, якщо він заданий, містить один або більше ідентифікаторів, розділених комами. Ідентифікатори в рядку параметрів повинні відрізнятися один від одного. Їх область дії обмежена макровизначенням. Список параметрів повинен бути заключений в круглі дужки. Імена формальних параметрів у тексті відмічають позиції, в які повинні бути підставлені фактичні аргументи макровиклику. Кожне ім'я формального параметра може з'явитися в тексті довільне число разів.     В макровиклику слід за ідентифікатором записувати в круглих дужках список фактичних аргументів, що відповідають формальних параметрам із списку параметрів. Текст модифікується шляхом заміни кожного формального параметра на відповідний фактичний параметр. Списки фактичних параметрів і формальних параметрів повинні містити одне і те ж число елементів.     Примітка. Не слід плутати підстановку аргументів в макровизначеннях з передачею параметрів у функціях. Підстановка в препроцесорі носить чисто текстовий характер. Ніяких обчислень при перетворенні типу при цьому не виконується.     Вище вже говорилося, що макровизначення може містити більше одного входження даного формального параметра. Якщо формальний параметр представлений виразом з "побічним ефектом" і цей вираз буде обчислюватися більше одного разу, разом з ним кожний раз буде виникати і "побічний ефект". Результат виконання в цьому випадку може бути помилковим.     В середині тексту в директиві #define можуть знаходитися вкладені імена інших макровизначень або констант.     Після того, як виконана макропідстановка, отриманий рядок знову переглядається для пошуку інших імен констант і макровизначень. При повторному перегляді не розглядається ім'я раніше проведеної макропідстановки. Тому директива #define a aне призведе до за циклювання препроцесора.Приклад 1.#define WIDTH 80#define LENGTH (WIDTH+10)     В даному прикладі ідентифікатор WIDTH визначається як ціла константа із значенням 80, а ідентифікатор LENGTH - як текст (WIDTH+10). Кожне входження ідентифікатора LENGTH у програму буде замінено на текст (WIDTH+10), який після розширення ідентифікатора WIDTH перетвориться на вираз (80+10). Дужки дозволяють уникнути помилок в операторах, подібних наступному :val=LENGTH*20;     Після обробки програми препроцесором текст набуде вигляду : val=(80+10)*20;.     Значення, яке буде присвоєно змінній val рівне 1800. При відсутності дужок значення val буде рівне 280.val=80+10*20;Приклад 2 .#define MAX(x,y) ((x)>(y))?(x):(y)     В даному прикладі визначається макровизначення MAX. Кожне входження ідентифікатора MAX в тексті програми буде замінено на вираз ((x)>(y))?(x):(y), в якому замість формальних параметрів x та y підставляються фактичні. Наприклад, макровиклик :MAX(1,2)

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

((1)>(2))?(1):(2).

Директива #undef      Синтаксис :#undef ідентифікатор.     Визначення символічних констант і макросів можуть бути анульовані за допомогою директиви препроцесора #undef. Таким чином, область дії символічної константи або макросу починається з місця їх визначення і закінчується явним їх анулюванням директивою #undef або кінцем файла.      Після анулювання ідентифікатор може бути знову використаний директивою #define.Приклад 3.#define WIDTH 80     /* … */#undef WIDTH     /* … */#define WIDTH 20

Директиви #if, #elif, #else, #endif      Умовна компіляція дає можливість програмісту керувати виконанням директив препроцесора і компіляцією програмного коду. Кожна умовна директива препроцесора обчислює значення цілочисельного константного виразу.      Умовна директива препроцесора #if багато в чому схожа на оператор if. Її синтаксис має вигляд .#if умова...[ #elif умова][ #elif умова     …][ #else      …]#endif     Умова - це цілочисельний вираз. Якщо цей вираз повертає не нуль (істинно), то фрагмент коду, що розташований між директивою #if і директивою #endif, компілюється. Якщо ж вираз повертає нуль (хибно), то цей фрагмент коду ігнорується і препроцесором, і компілятором. В умовах, окрім звичайних виразів, можна використовувати конструкцію :defined (ідентифікатор).defined повертає 1, якщо вказаний ідентифікатор раніше був визначений директивою #define, і повертає 0 в протилежному випадку.      Кількість директив #elif - довільна. Якщо директива #else присутня, то між нею і директивою #endif на даному рівні вкладеності не повинно бути інших директив #elif.Приклад 4:#if defined(CREDIT)     credit();#elif defined (DEBIT)     debit();#else     printerror();#endif     В наведеному прикладі директиви #if, #elif, #else, #endif керують викликом однієї з трьох викликів функцій. Виклик функції credit() скомпілюється, якщо визначена іменована константа CREDIT. Якщо визначена іменована константа DEBIT, то скомпілюється виклик функції debit(). Якщо жодна із наведених іменованих констант не визначена, то скомпілюється виклик функції printerror(). Приклад 5.#if DLEVEL>5#define SIGNAL 1#if STACKUSE == 1#define STACK 200#else#define STACK 100#endif#else#define SIGNAL 0#if STACKUSE == 1#define STACK 100#else #define STACK 50#endif#endif     В цьому прикладі показано два вкладених набори директив #if, #else, #endif. Перший набір директив обробяється, якщо значення DLEVEL більше за 5. В протилежному випадку оброблюється другий набір.

Директива #error      Директива #error викликає під час компіляції повідомлення про помилку.

#error повідомлення_про_помилку

Приклад 6. Забезпечення правильності параметрів компіляції.

#іf !defіned(__cplusplus)

# error Цей файл повинен компілюватися в режимі С++

#endіf

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

Директиви #ifdef і #ifndef      Синтаксис :#ifdef ідентифікатор#ifndef ідентифікатор.

     Аналогічно директиві #if, за директивами #ifdef і #ifndef може слідувати набір директив #elif і директива #else. Набір директив повинен закінчуватися директивою #endif.Використання директив #ifdef і #ifndef еквівалентне директиві #if, що використовує вираз з операцією defined (ідентифікатор). Ці директиви підтримуються виключно для сумісності з попередніми версіями компіляторів мови С. Тому замість цих директив рекомендується використовувати директиву #if з операцією defined (ідентифікатор).      Коли препроцесор оброблює директиву #ifdef, він перевіряє, чи визначений в даний момент вказаний ідентифікатор. Якщо так, то умова вважається істинною, якщо ні - хибною.Директива #ifndef протилежна за своєю дією директиві #ifdef. Якщо ідентифікатор не був визначений директивою #define, або його дія відмінена директивою #undef, то умова вважається істинною. В протилежному випадку умова хибна.

Директива #line      Синтаксис :#line константа ["ім'я_файла"].     Директива препроцесора #line повідомляє компілятору про зміну імені програми і порядку нумерації рядків. Ці зміни відбиваються лише на повідомленнях компілятора : файл програми буде тепер іменуватися як "ім'я_файла", а поточний рядок, що компілюється отримує номер, вказаний константою. Після обробки чергового рядка лічильник номера рядка збільшується на одиницю. У випадку зміни номера рядка й імені файла програми директивою #line, компілятор "забуває" їх попереднє значення і продовжує роботу вже з новими значеннями.     Поточний номер рядка і ім'я файла програми доступні в програмі через псевдозмінні з іменами __LINE__ і __FILE__. Ці псевдозмінні можуть використовуватися для виведення під час виконання програми повідомлень про точне місцезнаходження помилки. Значенням псевдозмінної __FILE__ є рядок, що представляє ім'я файла, заключене в подвійні лапки. Тому для друку імені файлу програми не потрібно заключати сам ідентифікатор __FILE__ в подвійні лапки.

Директива #pragma      У директиви #pragma є кілька застосувань.

1. #pragma argsused - не виводить попередження про невикористання параметра функції, розташованої слідом за директивою.

2. #pragma exіt - вказує функцію типу voіd fff ( ), що буде викликана перед завершенням програми.

3. #pragma hdrfіle - специфікує ім'я заздалегідь відкомпільованого файлу-заголовка.

4. #pragma hdrstop - пропонує компіляторові не включати подальшу інформацію в підключаємий під час компіляції заголовок.

5. #pragma іnlіne - пропонує компіляторові, що компіляція поточного модуля повинна проводитися через асемблер.

6. #pragma іntrіnsіc - дозволяє/забороняє генерацію іnlіne-кода для вбудованої функції.

7. #pragma optіon - включає в код опції командного рядка компілятора.

8. #pragma saveregs - гарантує, що обумовлена далі функція збереже регістри.

9. #pragma startup - указує функцію типу voіd fff(), що буде викликана перед початком програми.

10. #pragma warning - вибірково дозволяє або забороняє попереджуючі повідомлення.

11. #pragma once - пропонує компіляторові лише один раз включати даний заголовний файл у програму.

 © 2008 ХНУРЭ, Інформатики, Сінельнікова Т.Ф., informatika@kture.Kharkov.uaРозроблено за допомогою LERSUS

Соседние файлы в папке content