Главная » Просмотр файлов » М. Бен-Ари - Языки программирования. Практический сравнительный анализ (2000)

М. Бен-Ари - Языки программирования. Практический сравнительный анализ (2000) (1160781), страница 22

Файл №1160781 М. Бен-Ари - Языки программирования. Практический сравнительный анализ (2000) (М. Бен-Ари - Языки программирования. Практический сравнительный анализ (2000)) 22 страницаМ. Бен-Ари - Языки программирования. Практический сравнительный анализ (2000) (1160781) страница 222019-09-19СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 22)

end Proc_2;

begin – Main

end Main;

Глубина вложения

Принципиальных ограничений на глубину вложения нет, но ее может произ­вольно ограничивать компилятор. Область действия и видимость определя­ются правилами, данными выше: область действия переменной — от точки ее объявления до конца блока, а видимость — такая же, если только не скрыта внутренним объявлением. Например:

procedure Main is

Ada

Global: Integer;

procedure Level_1 is

Local: Integer; -- Внешнее объявление Local

procedure Level_2 is

Local: Integer; --Внутреннее объявление Local

begin -- Level_2

Local := Global; -- Внутренняя Local скрывает внешнюю Local

end Level_2;

begin -- Level_1

Local := Global; -- Только внешняя Local в области действия

Level_2:

end Level_1;

begin -- Main

Level_1;

Level_2; -- Ошибка, процедура вне области действия

end Main;

Область действия переменной Local, определенной в процедуре Level_1, про­стирается до конца процедуры, но она скрыта внутри процедуры Level_2 объ­явлением того же самого имени.

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

Обратите внимание на возможность запутаться из-за того, что обращение к переменной Local в теле процедуры Level_1 отстоит от объявления этой переменной дальше по тексту программы, чем объявление Local, заключенной внутри процедуры Level_2. В случае многочисленных локальных процедур найти правильное объявление бывает трудно. Чтобы избежать путаницы, луч­ше всего ограничить глубину вложения двумя или тремя уровнями от уровня главной программы.

Преимущества и недостатки блочной структуры

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

procedure Proc(...) is

-- Большое количество объявлений

begin

-- Длинное вычисление 1

Ada

if N < 0 then

-- Длинное вычисление 2, вариант 1

elsif N = 0 then

-- Длинное вычисление 2, вариант 2

else

-- Длинное вычисление 2, вариант 3

end if;

-- Длинное вычисление 3

end Proc;

В этом примере мы хотели бы не записывать три раза Длинное вычисление 2, а оформить его как дополнительную процедуру с одним параметром:

procedure Proc(...) is

-- Большое количество объявлений

procedure Long_2(l: in Integer) is

begin

-- Здесь действуют объявления Proc

Ada

end Long_2;

begin

-- Длинное вычисление 1

if N<0thenl_ong_2(1);

elsif N = 0 then Long_2(2);

else Long_2(3);

end if;

-- Длинное вычисление З

end Proc;

Однако было бы чрезвычайно трудно сделать Long_2 независимой процеду­рой, потому что пришлось бы передавать десятки параметров, чтобы она мог­ла обращаться к локальным переменным. Если Long_2 — вложенная процеду­ра, то нужен только один параметр, а к другим объявлениям можно непосред­ственно обращаться в соответствии с обычными правилами для области дей­ствия и видимости.

Недостатки блочной структуры становятся очевидными, когда вы пыта­етесь запрограммировать большую систему на таком языке, как стандарт Pascal, в котором нет других средств декомпозиции программы.

• Небольшие процедуры получают чрезмерную «поддержку». Предполо­жим, что процедура, преобразующая десятичные цифры в шестнадцате-ричные, используется во многих глубоко вложенных процедурах. Такаясервисная процедура должна быть определена в некотором общем пред­шествующем элементе. На практике в больших программах с блочной структурой проявляется тенденция появления большого числа неболь­ших сервисных процедур, описанных на самом высоком уровне объявле­ний. Это делает текст программы неудобным для работы, потому что нужную программу бывает просто трудно разыскать.

• Защита данных скомпрометирована. Любая процедура, даже та, объявле­ние которой в структуре глубоко вложено, может иметь доступ к глобаль­ным переменным. В большой программе, разрабатываемой группой про­граммистов, это приводит к тому, что ошибки, сделанные младшим чле­ном группы, могут привести к скрытым ошибкам. Эту ситуацию можно сравнить с компанией, где каждый служащий может свободно обследо­вать сейф в офисе начальника, а начальник не имеет права проверять картотеки младших служащих!

Эти проблемы настолько серьезны, что каждая коммерческая реализация Pascal определяет (нестандартную) структуру модуля, чтобы иметь возмож­ность создавать большие проекты. В главе 13 мы подробно обсудим конструк­ции, которые применяются для декомпозиции программы в таких современ­ных языках, как Ada и C++. Однако блочная структура остается важным инс­трументом детализированного программирования отдельных модулей.

Понимать блочную структуру важно также и потому, что языки програм­мирования реализованы с использованием стековой архитектуры, которая непосредственно поддерживает блочную структуру (см. раздел 7.6).

7.5. Рекурсия

Чаще всего (процедурное) программирование использует итерации, то есть циклы; однако рекурсия — описание объекта или вычисления в терминах са­мого себя — является более простым математическим понятием, а также мощ­ной, но мало используемой техникой программирования. Здесь мы рассмот­рим, как программировать рекурсивные подпрограммы.

Наиболее простой пример рекурсии — функция, вычисляющая фактори­ал. Математически она определяется как:

0! = 1

n! = п х (п - 1)!

Это определение сразу же переводится в программу, которая использует рекурсивную функцию:

int factorial(int n)

C

{

if (n == 0) return 1 ;

else return n * factorial(n - 1);

}

Какие свойства необходимы для поддержки рекурсии?

• Компилятор должен выдавать чистый код. Так как при каждом обраще­нии к функции factorial используется одна и та же последовательность машинных команд, код не должен изменять сам себя.

• Должна существовать возможность выделять во время выполнения про­извольное число ячеек памяти для параметров и локальных переменных.

Первое требование выполняется всеми современными компиляторами. Самоизменяющийся код — наследие более старых стилей программирования и используется редко. Обратите внимание, что если программа предназначена для размещения в постоянной памяти (ROM), то она не может изменяться по определению.

Второе требование определяется временем жизни локальных переменных. В примере время жизни формального параметра n — с момента, когда проце­дура вызвана, до ее завершения. Но до завершения процедуры делается еще один вызов, и этот вызов требует, чтобы была выделена память для нового формального параметра. Чтобы вычислять factorial(4), выделяется память для 4, затем 3 и т. д., всего пять ячеек. Нельзя выделить память перед выполнени­ем, потому что ее количество зависит от параметра функции во время выпол­нения. В разделе 7.6 показано, как это требование выделения памяти непо­средственно поддерживается стековой архитектурой.

Большинство программистов обратит внимание, что функцию, вычисляю­щую факториал, можно написать так же легко и намного эффективнее с по­мощью итерации:

int factorial(int n)

{

C

int i = n;

result = 1;

while (i != 0) {

result = result * i;

i--;

}

return result;

}

Так почему же используют рекурсию? Дело в том, что многие алгоритмы мож­но изящно и надежно написать с помощью рекурсии, в то время как итераци­онное решение трудно запрограммировать и легко сделать ошибки. Приме­ром служат алгоритм быстрой сортировки и алгоритмы обработки дре­вовидных структур данных. Языковые понятия, рассматриваемые в гл. 16 и 17 (функциональное и логическое программирование), опираются исключительно на рекурсию, а не на итерацию. Даже для обычных языков типа С и Ada рекурсию, вероятно, следует использовать более часто, чем это делается, из-за краткости и ясности программ, которые получаются в результате.

7.6. Стековая архитектура

Стек — это структура данных, которая принимает и выдает данные в порядке LIFO — Last-In, First-Out (последним пришел, первым вышел). Конструкции LIFO существуют в реальном мире, например стопка тарелок в кафетерии или пачка газет в магазине. Стек может быть реализован с помощью массива или списка (см. рис. 7.5). Преимущество списка в том, что он не имеет границ, а его размер ограничен только общим объемом доступной памяти. Массивы же намного эффективнее и неявно используются при реализации языков про­граммирования.

Кроме массива (или списка) в состав стека входит еще один элемент — указатель вершины стека (top-of-stack pointer). Это индекс первой доступной пустой позиции в стеке. Вначале переменная top будет указывать на первую позицию в стеке. На стеке допустимы две операции — push (поместить в стек) и pop (извлечь из стека), push — это процедура, получающая элемент как па­раметр, который она помещает в вершину стека, увеличивая указатель вершины стека top. pop — это функция, которая возвращает верхний элемент стека, уменьшая top, чтобы указать, что эта позиция стала новой пустой пози­цией.

Следующая программа на языке С реализует стек целых чисел, используя массив:

C

#define Stack_Size 100

int stack[Stack_Size];

int top = 0;

void push(int element)

{

if (top == Stack_Size) /* Переполнение стека, предпримите

что-нибудь! * I

else stack[top++] = element;

}

int pop(void)

{

if (top == 0) /* Выход за нижнюю границу стека,

предпримите то-нибудь! */

else return stack[--top];

}

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

Выделение памяти в стеке

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

Рассмотрим программу с локальными процедурами:

procedure Main is

G: Integer;

Ada

procedure Proc_1 is

L1: Integer;

begin ... end Proc_1 ;

procedure Proc_2 is

L2: Integer;

begin... end Proc_2;

begin

Proc_1;

Proc_2;

end Main;

Когда начинает выполняться Main, должна быть выделена память для G. Ког­да вызывается Ргос_1, должна быть выделена дополнительная память для L1 без освобождения памяти для G (см. рис. 7.6а). Память для L1 освобождается перед выделением памяти для L2, так как Ргос_1 завершается до вызова Ргос_2 (см. рис. 7.66). Вообще, независимо оттого, каким образом процедуры вызывают друг друга, первый элемент памяти, который освобождается, явля­ется последним занятым элементом, поэтому память для переменных и пара­метров может отводиться в стеке.

Рассмотрим теперь вложенные процедуры:

procedure Main is

Характеристики

Тип файла
Документ
Размер
2,54 Mb
Тип материала
Высшее учебное заведение

Список файлов книги

Свежие статьи
Популярно сейчас
Как Вы думаете, сколько людей до Вас делали точно такое же задание? 99% студентов выполняют точно такие же задания, как и их предшественники год назад. Найдите нужный учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
6455
Авторов
на СтудИзбе
305
Средний доход
с одного платного файла
Обучение Подробнее