Информационный сайт

 

Реклама
bulletinsite.net -> Книги на сайте -> Программисту -> Непейвода Н.Н. -> "Основания программирования " -> 146

Основания программирования - Непейвода Н.Н.

Непейвода Н.Н., Скопин И.Н. Основания программирования — Институт компьютерных исследований , 2002. — 919 c.
Скачать (прямая ссылка): osnovanprogramm2002.pdf
Предыдущая << 1 .. 140 141 142 143 144 145 < 146 > 147 148 149 150 151 152 .. 316 >> Следующая

Передача параметра по наименованию (или, что то же — по имени) восходит к самым ранним языкам программирования (FOTRTRAN, Algol 60 и др.). Этот механизм на первый взгляд не вполне удовлетворителен с точки зрения надености программирования, тем не менее, полезно сопоставить его, в частности, с подстановкой параметров-переменных.
Пусть в условиях приводимых иллюстраций описана процедура с вызовом параметра по имени:
procedure R ( name x : Integer); begin
a := x; x := 1; end;
Это описание в указанном вые контексте позволяет употреблять проце-
8.5. ПАРАМЕТРИЗАЦИЯ
415
дуру для присваивания глобальной переменной a значения некоторого в -ражения, поставляемого фактическим параметром. А так как во втором операторе формальный параметр x является получателем значения, фактический параметр, подставляемй по наименовани (параметр-имя), мо ет быть только переменной. Если б в теле процедур не происходило присваивание значения параметру, то в качестве фактического параметра мо но было б употреблять и выражение (в данном случае целого типа).
В результате выполнения процедуры переменная x получает значение 1. Таким образом, операторы R(23); и R(2 + 2); некорректны, но не по причине использования выражений, а из-за наличия в теле R присваивания x := 1. Различные возможности вызова по имени проиллюстрированы на рис. 8.6. Полезно подробнее сопоставить последний вызов процедуры R с Q(M[a]) при
R(u); {u — нецелочисленная переменная или выражение}
некорректен из-за спецификатора Integer в заголовке процедуры, и это, вообще говоря, отношения к механизму передачи параметров не имеет, а означает просто несоответствие типов. Вместе с тем, допустим
R( b ); { если значение b до этого оператора определено, то это значение присваивается a, а переменной b присваивается 1}
R( a ); { значение, получаемое переменной a, есть 1, оно вырабатывается вторым оператором тела процедуры }
Эти вызовы имеют тот Же эффект, что и соответствующие №1-
зов процедуры Q. опустимы и следуие вызовы процедур , соответствуие Q(M[2]); и Q(M[a]), но с совсем инм эффектом во втором случае:
R(M[2]); { значение M[2] станет значением переменной a, затем M[2] получит новое значение 1}
R(M[a]); { вызов всегда корректен, возмо на оибка при вычислении значения M[a], если неверно 0 ^ a ^ 3. Результат первого оператора тела — изменение значения переменной a. Если для нового значения a верно 0 ^ a ^ 3, то корректен оператор x:=1 . Его эффект — присваивание значения 1 переменной M[a], где у a новое значение }
Рис. 8.6. Вызов по наименованию
тех е значениях переменных. В соответствии с определением при вызове R(M[a]) имитируется подмена параметра x на M[a]. Поэтому первый опера-
416
ГЛАВА 8. ПОДПРОГРАММЫ
тор тела процедуры, как и в случае Q(M[a]), присваивает значение 3 переменной a, но далее текстуальная замена x на M[a] в операторе x:=1 приводит к присваиванию значения 1 переменной M[3] (а не M[1], как при Q(M[a])).
з примеров видно, что достигается при подстановке параметра по наименованию: системой программирования обеспечивается такой эффект выполнения вызова процедуры, как при вполнении тела процедур , в котором всякое вхождение в текст формального параметра заменено фрагментом текста, представляющего соответствующий фактический параметр.
риведенное ве определение передачи параметров не совсем корректно: понимаемое буквально, оно противоречит отмеченному обему принципу разделения контекстов: формальные параметры относятся к контексту процедуры, а фактические к контексту ее вызова. Иллюстрацией служит пример на рис. 8.7. При буквальном понимании определения, переменная a, по-
var a : Integer;
procedure P(name x : Integer); begin
... x ... { Текстуальная замена x на a приводит }
end; { P } { идентификатор a в контекст, в котором }
procedure Q( . . . ); { он понимается как имя глобальной переменной a,}
var a, b : Integer; {в то время как в точке вызова} begin { a понимается как локальная переменная процедуры }
... P ( a ); ...
... P ( b ); ... end; { Q }
Рис. 8.7. лохой вызов по наименовани
являаяся при подстановке фактического параметра вместо x, оказвается той переменной, которая описана в первой строке примера, а переменная b (второй вызов P) и вовсе недоступна. С любой разумной точки зрения это неверно, и требуется уточнение, которое в декларативной форме выглядит как конкретизация принципа разделения контекстов: имена из фрагментов, вста-вляемх вместо формальнх параметров, идентифициру тся, исходя из их доступности в контексте вызова, а не описания процедур . редством до-
8.5. ПАРАМЕТРИЗАЦИЯ
417
сти ения этого мо ет быть переименование переменных, т. е. замена всех вхождений конфликтных имен новыми уникальными именами (в полном соответствии с тем, как подобная процедура производится в логических системах при оперировании со свободными и связанными переменнми).
В реализационном плане коллизии имен ликвидиру тся с помоь остроумного метода санков (thunk), предложенного Ингерманом еще для Algol 60. Суть метода в том, что в объектном коде контекст вызова процедуры пополняется специальными подпрограммами для каждого фактического параметра (именно они и назва тся санками). ри исполнении взова обраение к параметру интерпретируется как вызов санка данного параметра.
Предыдущая << 1 .. 140 141 142 143 144 145 < 146 > 147 148 149 150 151 152 .. 316 >> Следующая
Реклама
Авторские права © 2009 AdsNet. Все права защищены.
Rambler's Top100