Шрифт:
Директива #define может быть записана в двух синтаксических формах:
#define идентификатор текст
#define идентификатор (список параметров) текст
Данная директива заменяет все дальнейшие вхождения идентификатора на текст. Подобный процесс называется макроподстановкой. Текст может быть любым фрагментом программы на СИ, а также может и отсутствовать.
18. Применение директив
Рассмотрим пример:
#define WIDTH 80
#define LENGTH (WIDTH+10)
Данные директивы заменят в тексте программы каж дое слово WIDTH на число 80 и любое слово LENGTH н выражение (80+10) вместе с окружающими его скобками
Скобки, которые содержатся в макроопределении дают возможность избежать недоразумений, связан ных с порядком вычисления операций. К примеру, есл1 в скобках выражение t = LENGTH*7 будет преобразова но в выражение t = 80 + 10*7, а не в выражение t = (80 – + 10)*7, как это получается, если есть скобки, в резуль тате будем иметь 780, а не 630.
Во второй синтаксической форме в директиве #define присутствует список формальных параметров, которы может включать в себя один или несколько идентифика торов, которые разделены запятыми. Формальные пара метры в тексте макроопределения отмечают позиции на которые должны быть подставлены фактические ар гументы макровызова. Любой формальный параметр способен появиться в тексте макроопределения несколь ко раз.
При макровызове за идентификатором следует спи сок фактических аргументов, количество которых сле дует сделать совпадающим с количеством формальны параметров.
Пример:
#define MAX(x,y) ((x) > (y))?(x): (y)
Приведенная директива заменит фрагмент t = = MAX(i,s[i]) на выражение t = ((i) > (s[i])?(i): (s[i]).
Как и в ранее приведенном примере, круглые скобки, в которые заключены формальные параметры макроопределения, дают возможность избежать ошибок, связанных с неправильным порядком осуществления, если фактические аргументы являются выражениями.
Например, если есть скобки, фрагмент
t = MAX(i&j, s[i]||j) будет заменен выражением
t = ((i&j) > (s[i]||j)?(i&j): (s[i]||j); а если скобок нет – фрагментом
t = (i&j>s[i]||j)?i&j: s[i]||j;
где условное выражение вычисляется в другом порядке.
Директива #undef применяется для отмены действия директивы #define. Синтаксис данной директивы следующий: #undef идентификатор.
Директива отменяет операцию текущего определения #define для определенного идентификатора.
19. Рекурсия
Функция является рекурсивной, когда во время обработки появляется ее повторный вызов непосредственно или косвенно, через цепочку вызовов других функций.
Прямая (непосредственная) рекурсия – это вызов функции внутри тела этой функции.
int a
{…..a…..}
Косвенная рекурсия – это рекурсия, которая осуществляет рекурсивный вызов функции через цепочку вызова других функций. Все функции, которые входят в цепочку, тоже являются рекурсивными. Рассмотрим пример:
a{…..b…..}
b{…..c…..}
c{…..a…..}.
Все представленные функции a, b, c считаются рекурсивными, так как в случае вызова одной из них производится вызов других и самой себя.
Последовательность вызовов процедуры tn, если m = 3, можно проиллюстрировать древовидной структурой (рис. 2). Всякий раз при вызове процедуры tn под параметры n, i, j, w определяется память и запоминается место возврата. В случае возврата из процедуры tn память, которая выделяется под параметры n, i, j, w, освобождается и становится доступной память, которая выделена под параметры n, i, j, w предыдущим вызовом, а управление передается в место возврата.
Рис. Последовательность вызовов процедуры tn
Очень часто рекурсивные функции можно заменить нерекурсивными функциями или фрагментами. Это производится путем использования стеков для хранения точек вызова и вспомогательных переменных.
20. Знакомство с языком СИ++
Рассмотрим ряд программ и частей программ на C++.
Прежде всего, рассмотрим программу, которая выводит строку выдачи:
#include
main
{
cout << «Hello, world\n»; }