Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Проектирование программ и программирование на С++ Часть 1. Структурное.pdf
Скачиваний:
18
Добавлен:
15.11.2022
Размер:
3.8 Mб
Скачать

20.4. Условная компиляция

Для условной компиляции используются следующие команды:

# i f константное выражение

позволяют выполнить проверку

# i f d e f

препроцессорный

и ден ­ условий

тификатор

 

i i f n d e f

препроцессорный

иден ­

тификатор

 

# e is e

 

позволяют определить диапазон дей­

# e n d if

 

ствия проверяемого условия.

Общая структура применения директив условной компиляции следующая:

# i f у сл о в и е т е к с т 1

#e ls e т ек ст 2

#e n d if

Конструкция #else текст2 необязательна. Текст1 включа­ ется в компилируемый текст только при истинности проверяемого условия. Если условие ложно, то при наличии директивы else на компиляцию передается текст2, если эта директива отсутствует, то

при ложном условии текст 1 просто опускается.

Различие между форматами команд # i f следующее:

1. Директива # i f константное_ вы раж ение проверяет зна­

чение константного выражения. Если оно отлично от нуля, то счита­ ется, что проверяемое условие истинно.

2. В директиве # i f d e f препроцессорный

идентификатор про­

веряется, определен ли с помощью директивы

ttd e fin e и д ен ти ­

фикатор, помещенный после # i f d e f . Если идентификатор опреде­ лен, то т е к с т 1 используется компилятором.

3. В директиве # if n d e f препроцессорный идентификатор про­ веряется обратное условие: истинным считается неопределенность идентификатора. Если идентификатор не определен, то т е к с т 1 ис­ пользуется компилятором.

Файлы, которые предназначены для препроцессорного включения, обычно снабжают защитой от повторного включения. Такое повторное включение может произойти, если несколько модулей, в каждом из ко­ торых подключается один и тот же файл, объединяются в общий текст

программы. Такими средствами защиты снабжены все заголовочны

файлы стандартной библиотеки (например, iostream. h).

Схема защиты от повторного включения:

//Файл с именем filename включается в другой //файл

#ifndef _FILE_NAME

....//включаемый текст файла filename #define _FILE_NAME 1

#include <...>//заголовочные файлы

<текст модуля>

#endif

FILE NAME - зарезервированный для файла filename препро-

цессорный идентификатор, который не должен встречаться в других

текстах программы.

20.5. Макроподстановки средствами препроцессора

Макрос, по определению, есть средство замены одной последо­ вательности символов на другую. Для выполнения замен должны быть заданы соответствующие макроопределения.

С помощью директивы # d e f in e идентификатор с т р о - ка_зам ещ ения можно вводить макроопределения, в которых строка замещения фиксирована. Большими возможностями обладает макро­ определение с параметрами:

#define имя (список_параметров) строка_замещения

Здесь имя - это имя макроса (идентификатор), список_параметров - список разделенных запятыми идентификаторов.

//пример 1

#define max(a,b) (a<b?b:а)//макроопределение

max(x,y)// заменяется выражением (х<у?у:х) max(z,4)// заменяется выражением (z<4?4:z) //пример 2

#define ABS(x) (х<0?-(х):х)//макроопределение

ABS(E-Z)//заменяется выражением (E-Z<0?-(E-Z):E-Z)

Отличия макроса от функции:

1.Определение функции присутствует в программе в одном эк­ земпляре, коды, формируемые макросом, вставляются в программу столько раз, сколько используется макрос. В этом отношении макро­ сы похожи на inline-функции, но подстановка для макроса выполня­ ется всегда.

2.Функция определена для данных того типа, который указан

вспецификации и возвращает значения только одного конкретного типа. Макрос пригоден для обработки параметров любого типа. Тип полученного значения зависит от типов параметров и самих выраже­ ний. В примерах 1 и 2 в качестве параметров могут использоваться любые целочисленные или вещественные типы.

Механизм перегрузки и шаблоны функций позволяют решать те же проблемы, что и макросы, поэтому в программах на C++ макро­ средства используются реже, чем в программах на базовом С.

#define max(a,b) (a<b?b:a) #define t(e) e*3

#define PRN(c) cout<<"\n"«#c«" равно ,,;cout«c;

#define E x*x

#include<iostream.h> void main()

{

int x=2;

PRN(max(++x,++x);

PRN(t(x));

PRN(t(x+x));

PRN(t(x+x)/3);

PRN(E);

}

При подстановке параметров макроса в строку замещения за­ прещены подстановки внутрь кавычек, апострофов или ограничите­ лей комментариев. При необходимости параметр макроса можно заключить в строке замещения в кавычки, для этого используется операция #, которая записывается перед параметром.

Примеры подстановок параметров макроса:

P R N (m ax(+ + х ,+ + х );

P R N (t (х ));

P R N ( t (х + х ) );

P R N ( t (х + х )/ 3 ) ;

P RN(E) ;

1- я подстановка

cout<<"\n"<<"m ax (++х, ++х) " « " равно " ;c o u t< < m ax(+ + х ,+ + х );

2- я подстановка

c o u t< < //\ n //<<//max (+ + х,+ + х) "<<" равно

"; cou t< < (++х<++х?++х:++х) ; / / т.е. х увели­ чится на 3 (=5)

1- я подстановка

c o u t « " \ n " « " t (х) " « " равно " ; c o u t « t (х)

2-

я подстановка

 

c o u t< < " \n " < < " t( х ) " < < " равно

 

c o u t « x * 3 ; //х = 5 , результат 15

1-

я подстановка

 

c o u t< < " \n " < < " t (х+х) ” « "

равно " ; c o u t «

t (х+х)

 

2-

я подстановка

 

c o u t< < /'\n " < < //t (х+х) ” « "

равно

 

cou t< < (х+х) *3; //х = 5 , результат 30

1-

я подстановка

 

c o u t< < " \n " < < " t (х+х) " << " равно //; c o u t «

t (х + х )/3

 

2-

я подстановка

 

c o u t< < " \n //<<//t (х + х )" « "

равно

 

co u t< < (х+х) * 3 /3 ; / / результат (5+5)-3/3=10

1-

я подстановка

 

c o u t< < " \n //<<"E,/<<#/ равно ";cout<<E ;

2-

я подстановка

 

c o u t < < //\ n /,< < /#E'/< < /'р а в н о "; c o u t < < x * x ; / / результат 25

Результаты:

т а х ( + + х , + + х ) равно 5

t

(х ) равно 15

t

(х+х) равно 20

t( х + х ) / 3 равно 10

Еравно 25.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]