Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Розділ 10. Базові засоби мови С++.docx
Скачиваний:
6
Добавлен:
01.05.2019
Размер:
366.53 Кб
Скачать

Самостійна робота. Директиви препроцесора

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

Примітка. Після директив препроцесора крапка з комою не ставиться.

1. Директива #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 слідує рядок, що заключений в лапки або в кутові дужки, то ТС не буде шукати в ній ім'я константи.

#define myincl "c:\test\my.h"

#include myincl

2 Директива #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).