Т. Пратт, М. Зелковиц - Языки программирования - разработка и реализация (4-е издание_ 2002) (1160801), страница 125
Текст из файла (страница 125)
Рассмотрим следующую программу, написанную на языке, в котором ис- пользуются правила статической области видимости: ргодгав ва1пм проС,острот); чаг КЭ.Ь,е: птедег, ргосеооге 0(чаг и 1'пгедег: и: штедег): Ьед1п юань 9.6. Задачи и упражнения 466 е. )+1, нгые1п(!.Эд.а) ело. ргасееоге Р(чаг ы !п1ечег: Эр ~п(ечег); каг 1: щ(ечег. Ьео!и 1:-ч: 3'")~1: О(!.1) епо; Ькя(л (:-1; 1:=2; 1: 3; Р(! 'к); нгтге1п(!.Эж) еле. Заполните следующую таблицу для каждого оператора иг(1е1 и в предположении, что передача параметров осуществляется указанным способом. Способ передачи параметров ] к гп Язык Рааса(, как записаны е программе Все параметры передаются по ссылке Все параметры передаются по значению Все параметры передаются по значению-результату 13.
Ссылки на массивы с использованием вычисляемых индексов (например, д[1)) иногда рассматриваются как некоторая форма создания псевдонимов. Например, два составных имени д[]] и яИ можно считать псевдонимами. Объясните, почему использование таких ссылок на массивы создает для программиста и для разработчика некоторые из тех же проблем, которые возникают при использовании других типов псевдонимов.
14. В языке г ОКТКА]ч] требуется, чтобы объявление для каждого объекта данных, совместно используемого через общую среду (СОМ МО]к]-блок), задавалось в каждой подпрограмме, которая его использует. Это позволяет компилировать каждую подпрограмму независимо, так как в каждой из них содержатся полные объявления для всех совместно используемых объектов. Предположим, что программист случайно задал слегка разные объявления в каждой из двух подпрограмм 5иЫ и 5оЬ2, которые совместно используют переменную к. Что произойдет, если 5цЫ и 5оЬ2 будут скомпилированы по отдельности, а затем собраны в одной программе, которая будет выполнена? Положим, что во время выполнения объект данных к будет представлен в соответствии с объявлением, данным в 5иЫ, а не в 5иЬ2. 15.
Предположим, что подпрограмма0(см. листинг 9.7) была бы вызвана из подпрограммы Р с использованном констант в качестве фактических параметров(например,0(2. 3) вместо 0(а, $Ь)). Хотя передача констант поссылке в С запре!цена, но во многих других языках это допускается, поэтому будем считать, что такая передача констант допустима и здесь. Напомним: 466 глава 9. Управление подпрограммами а) Объект данных, представляющий константу, обычно хранится в сегменте кода вызывающей подпрограммы. б) Выражение фактического параметра, состоящее из одной константы, являешься частным случаем произвольного выражения, служащего фактическим параметром. Предложите два метода реализации передачи константы: по значению и по ссылке.
В первом методе не используется временное хранение объекта данных в вызывающей программе, а во втором используешься. [Первый( метод, использованный для передачи по ссылке, может приводить к константам, изменяющим свои значения, — например, в некоторых реализациях РОКТКА[х[ можно написать программу, которая складывает 1 и 2, получая в результате 4.) Напишите ~акую программу и попробуйте выполнить ее в используемой вами реализации языка. [Подсказка: используйте следующую последовательность операторов; 5ищ1): Х:= 2: Х Х + 1; рг1пт(Х) и напишите подпрограмму 5иЬ таким образом, чтобы она изменяла на 2 значение ли~врала 1,) 16.
Прием Йенсена. Передача параметров по имени позволяет применить программистский трюк, известный как прием Йенсена. Вп) основная идея заключается в том, чтобы в подпрограмму передать по имени отдельными параметрами некоторое выражение, содержащее одну или более переменных, и сами эти переменные. Искусно изменяя значения этих переменных и используя ссылки на формальный параметр, соответствующий выражению, это выражение- параметр можно вычислить для многих различных значений переменных, Простой пример использования этого приема можно найти в следующей универсальной программе суммирования 5иа), написанной на языке А1.601л геа1 ргосеаиге 5ие (Ехрг.
!всех [В, ВВ). ча)ие [В, ВВ; геа1 Ехрг (реевег !пиех, ! В, ВВ; Ьеэ(о геа1 Теер: Теор = 0 Гог !всех := [В егер 1 иот(1 ВВ Во Тиар =ТеерхЕхрг: 5ив := Тевр еои 5ию В этой программе переменные Ехрг и !псех передаются по имени, а [В и 0В— по значению.
Результатом вызова 5аа(А[!1 1,1 25) будет сумма первых 25 элементов вектора А. При вызове 5ив(А[!!*В[!1 1 1 25) результатом будет сумма произведений первых 25 соответствующих элементов векторов А и В [если предположить, что Я и В объявлены подходящим образом). Вызов 5ив(С[К,2),К,-100 100) позволи~ г(олучить сумму элементов второго столбца матрицы С от С[-100, 21 до С[100. 21, 9.6.
Задачи и упражнения 457 17. В языках ЕОКТКАХ и Ада используется одинаковый синтаксис для ссылок 18. 19. 20. 21. а) При каком вызове 5пп можно получить сумму элементов главной диагонали матрицы О, объявленной как геа) аггау 011:50, 1:50)? б) При каком вызове 5пп) можно получить сумму квадратов первых 100 нечетных чисел? в) Используя описанный прием, напишите универсальную программу Ыах, которая будет возврашать максимальное из множества значений, получаемых при вычислении произвольного выражения Ехрг, содержащего целую переменную! поех, которая изменяется в пределах от1 В до 08 с шагом 51ер.
на компоненты массива и вызова подпрограмм-функций. Например, в записи А + В(Е, О) идентификатор В может означать как имя подпрограммы с двумя параметрами, так и двухмерный массив. Если объявлены имена всех массивов и подпрограмм, то такой синтаксис не приводит к неоднозначности. Но если какое-либо обьявление отсутствует, то у компилятора или загрузчика могут возникнуть проблемы.
При каких условиях компилятор мог бы осуществить правильную интерпретацию для пропущенного объявления? Главное отличие ЕОКТКАХ 90 от ЕОКТКАХ заключается в том, что он до- пускает в некоторых случаях динамическое выделение памяти. Перечисли- те те свойства языка, для которых требуется динамическое выделение памя- ти транслятором. Как реализовать рекурсивную функцию, например Еас1ог) а) (и), в языке ЕОКТКАХ 77, в котором память распределяется только статически? Какие пзлгепения следовало бы сдела~ь в организации времени выполнения языка С, чтобы можно было добавить к нему оператор )пт А[п! который размешает в лама~и массив размерол~ и и присваивает ему имя А в предположении, что и — переменная, объявленная в другом блоке? Мож)ю ли сделать то же самое в)ача? Почему? Операция выделения намял п)э) ) ос языка С часто реализуется как обраше- ние к программе распределения памяти, встроенной в операционную систе- му.
Операционная система организует центральную кучу, используемую всеми программами, а операции па) ) ос и 1гее, вызываемые из С-программы, соответственно выделяют и освобожлают память в этой центральной куче, Поскольку операция аа) ) ос требует обращения к операционной системе, этот процесс может занять много времени. Альтернативным вариантом реализа- ции операции па))ос является использование локальной кучи в адресном пространстве каждой программы. В таком случае использование этой опе- рации обходится значительно дешевле.
(Операция пеи в Рааса! реализована таким же образом.) Предположим, ваша программа разработана таким образом, что требует до- статочно частого использования операции а)а) ) ос для выделения небольших блоков памяти из кучи. 458 Глава 9, Управление подпрограммами Исследуйте вашу локальную реализацию С и определите, какова в атой реализации стоимость использования для указанных целей операции вз11ос.
Сравните эту стоимость со стоимостью использования кучи и операции аа11ос, которую вы могли бы реализовать сами как часть вашей программы. Рассмотрите два случая: а) ваша программа выделяет блоки памяти только одного размера; б) ваша программа выделяет блоки памяти различных размеров. 22. Вернемся к программе апопи1у из листинга 9.1. Определите, какой способ применяется в вашем локальном трансляторе Разса1 для разрешения объявлений тагнзгй.
23. Поскольку в языке Аг1а допускается располагать фактические параметры в парах с соответствующими формальными, используя имена формальных параметров в операторе вызова, имена формальных параметроа становятся видимыми в вызывающей программе. Обычно имена формальных паралгетров являются локальными для вызванной подпрограммы н не видимы для вызывающей подпрограммы. Объясните, почему подпрограмму, формальные параметры которой являются видимыми из вызывающей подпрограммы, легче модифицировать. Глава 10. Управление памятью В главе 9 мы обсуждали стековую структуру управления подпрограммами. Но в большинстве языков также имеется возможность динамически выделять и освобождать память для объектов данных некоторым произвольным образом.
Говорят, что для таких объектов память выделяется из кучи. Во многих реализациях стек начинается с одного конца памяти компьютера, а куча — с другого. Если эти две структуры — стек и куча — когда-либо встречаются, то программе не хватает памяти и она останавливается. В этой главе мы обсудим различные методы управления кучей, обусловленные требованиями, прелъявляемыми к языку программирования. Управление памятью для хранения данных является одной из основных забот программиста, разработчика языка и разработчика транслятора. В этой главе рассматриваются различные проблемы и методы управления памятью.
В типичных языках мы находим множество особенностей или ограничений, которые можно объяснить только желанием разработчиков применить тот или иной метод управления памятью. Рассмотрим, например, язык РОКТКАХ, в котором запрещаются рекурсивные вызовы подпрограмм. Рекурсивные вызовы можно было бы допустить в РОКТКАХ, даже не меняя его синтаксис, но реализация таких вызовов потребовала бы наличия стека точек возврата во время выполнения, а эта структура данных требует динамического управления памятью. ЕОКТКАХ, в котором запрещен рекурсивный вызов подпрограмм, может быть реализован с использованием только статического управления памятью.