Р.У. Себеста - Основные копцепции языков программирования (2001) (1160794), страница 95
Текст из файла (страница 95)
ъслты, содержащие скалярные величины. передаваться по ссылке мог>т). Ь(етод передачи параметров по значению и результату впервые был реализован в :: яке А(.ОО(. % (Ф(пп апг( Ноаге, 1966) в качестве альтернативы неэффективному мез> передачи по имени и вызывающему проблемы методу передачи по ссылке. В языках Рааса( и Модо(а-2 по умолчанию лля передачи параметров используется пе-.: шча по значению, а передача по ссылке может быть указана путем приписывания слез: к формальнолгу параметру зарезервированного слова чае. Разработчики языка Аба определили версии трех семантических молелей передачи .зрамстров: ввода, вывола и ввода-вывода. Эти трп режима соответственно называются .*.Резервированными словами Еп.
оцц и хц оцц, причем Ео является метолом по умол- нию. Рассмотрим следующий заголовок функциии на языке Аба: ркоовг(цкв йВВЕК(й: хп оис 1ИТЕВЕР„ В: кж 1((ТЕВЕйг С : оиа Г ОАТ) 3 языке Ада 83 формальным параметрам, передаваемым в режиме оцц, можно присваивать любые значения, однако на них нельзя ссылаться.
На параметры, передаваемые в 3.5. Методы передачи параметров режиме йп, можно ссылаться. но им нельзя ничего присваивать. Совершенно естественно. параметрам, перелаваемым в режиме дп оие, можно как присваивать значения. так и ссылаться на них. Вопрос о том, как именно реализована передача параметров в режиме 1п оио в языке Ас)а. представляет большой интерес и обсуждается в разделе 8.5.5. 8.$.Я. Проверка типов параметров В настоящее время принято считать, что надежность програмлгного обеспечения требует. чтобы типы фактических параметров проверялись на совместимость с типами соответствующих формальных параметров. Без такой проверки типов небольшая опечатка может привести к ошибке в работе программы, которую, возможно, булет сложно обнаружить.
поскольку такие ошибки не распознаются компилятором или системой поддержки выполнения программ. Рассмотрим следующий вызов функции: ЯЕЯШ Т: ЯУВ1 ( 1 ) Здесь фактический параметр является целочисленной константой. Если формальный параметр функции ЯБЯ1 имеет тип числа с плавающей точкой, то ошибка не будет обнаружена. если не предусмотрена проверка типов. Несмотря на то что целое число 1 и число с плавающей точкой 1 имеют одно н то же значение, их прелставлення очень сильно отличаются друг от друга. Функция ЯЯЯ1 не может вычислить правильный результат, получив целочисленный фактический параметр вместо числа с плавающей точкой.
В языке ГОКТКАХ 77 проверка типов не нужна. в то время как в языках Рааса!, Моди!а-2. РО((ТКА)л) 90. 3ача и Ада она предуслютрена. Проверка типов в языках С и Се+ требует отдельного разговора. В исходной версии языка С ни количество, нн типы параметров не проверялись. В языке А)ЧЯ( С формальные параметры функций можно было определить двумя способами.
Первый способ был тем же, что н в исходной версии С, т.е, имена параметров перечислялись в скобках, а объявления типов следовали за ними, как в следующем примере: с(оиЬ1е азг (х) с(оиЬ1е х; ( Использование этого метода позволяет избежать проверки типов и применять вызовы. подобные приведенному ниже: с(оиЬ1е ча1ие; дпо соипсг ча1ие = взп(соипс) Такие выювы допустимы, но бессмысленны. Альтернативой этому является метод прототипов (ргосо(уре ше()юб), в котором формальные параметры включаются в список, как показано ниже: с(оиЬ1е взп(с(оиЬ1е х) ( ° .
) Также вполне допустим следующий вызов варианта функции в(п: ча ие = в1п(соипс); 362 Гдово 8. Подпрограммы ". фактического параметра (Зпк) сравнивается с типом формального параметра ДоиЬ1е). Несмотря на то что онн не совпадают. тип хпк может быть приведен к типу ='еиЬ1е, позтому выполняется приведение типов. Если приведение типов невозможно - зример, если фактический параметр должен был быть л~ассивом) нли количество па-.
' строе является неверным, то распознается син1аксическая ошибка. Таким образом. в : . ыке АХБ! С пользователь сам решает, следует ли выполнять проверку типов. В языке С++ формальные параметры всех функций должны быть указаны в их протоцьх. Однако проверки типов некоторых параметров можно избежать. заменив послед- -. ю часть списка параметров эллипсисом, как показано ниже: ' пт б (аопвк спаг* ... ); .::зов функции ргзпг й дояжен иметь хотя бы олин параметр. являющийся указателем константную строку. Все остальное (включая отсутствие всех дружи параметров) яв:ется вполне допустимым.
Способ, которым функция рггпг б определяет. есть ли в выье дополнительные параметры, основывается на использовании специальных символов :. -араметре. являюшемся строкой. Например, форлгат для вывода целого числа имеет : з '. Он является частью строки, как в следуюшем прил~ере: -.г1пгг("Сумма равна З<з~п", впж]; чвол т сообшает компилятору о том, что в списке вывода есть еше один параметр. 8.5.5. Методы реализации передачи параметров Геперь рассмотрим вопрос о том, как в действительности реалпзук тся различные зели передачи параметров.
В языке АЕООЕ 60 и производных от него языках обмен параметрами происходит :гсз стек выполняемой программы (гцпчппе мас(г). Стек выполняемой программы ини. злизируется и поддерживается системой поддержки выполнения программ. Этот стек ...рока используется для управления подпрограммами и передачи параметров, как покао в главе 9. В холе последуюшего обсуждения мы будем предполагать, что стек исльзуется лля передачи всех параметров. Параметры, передаваемые по значению, копируются в ячейки стека. Эти ячейки загем " л ат хранилищем для соответствующих формальных параметров.
Передача параметров результату реализуется как противоположность передаче параметров по значению. Зна.: ия. присвоенные фактическим параметрам, передаваемым по результату. помешаются в .:к. откуда они могут быть извлечены яызываюшим программным модулем после завер;пня работы вызванной полпрограммы. Передача параметров по значению и рез)льтату жет быть реализована в соответствии со своей семантикой как комбинация передачи по -з ~гнию и передачи по результату.
5!чейка стека инициализируется выювом и затем ис.-.ьзуется как локальная переменная в вызываемой подпрограмме. Передача параметров по ссылке. возможно, наиболее проста для реализации. Незави;. чо от типа фактического параметра в стек должен помешаться лишь его атрее. Если -зоаметры являются литералами, то в подпрограмму передаются адреса литершнш.
Если — зраметр является выражением, то компилятор должен построить код для вычисления =ыражения непосредственно перед передачей управления в вызываемую подпрограмму. -'.дрес ячейки памяти, в которую код помешает результат своих вычислений, затем запи. ~вается в стек. Компилятор должен гарантировать, что вызываемая подпрограмма не 3.5. Методы передачи параметров 363 сможет изменить параметры, являющиеся литералами или выражениями, как показано ниже. Доступ к формальным параметрам в вызываемой подпрограмме осуществляется путем косвенной адресации по ячейке стека, содержащей нужный адрес. Реализации передачи по значению, по результату, по значению и результату, а также по ссылке, в которых используется стек выполняемой программы, показаны на рис.
8.2. Стек процедура коь прогремие. его Рис. 8.2. Вазиажнал реатизайия стека при испауьэовании основных .«елков переаачи параметров Неявная, но фатальная ошибка может возникнуть при передаче параметров по ссылке или по значению и результату, если не проявить осторожность при их реализации. Допустим. программа содержит две ссылки на константу 1О, и первая из этих ссылок является фактическим параметром в вызове некоей подпрограммы.
Предположим далее, что полпрограмма по ошибке изменила формальный параметр, соответствующий константе 1О. на константу 5. Компилятор этой программы может вылепить отдельную ячейку памяти для значения 1О во время компиляции, как это компиляторы часто и делают, а затем использовать эту ячейку лля всех ссылок на константу 1О в программе. Однако после возвращения из подпрограммы все последующие появления константы 10 булут заменены значением 5.
Если компилятор допускает такую ситуацию, то возникают проблемы программирования, которые очень трудно диагностировать. В действительности именно так все и происходило во многих реализациях языка ЕОКТВАХ 1Ч. Передача параметров по имени обычно реализуется с помощью процелуры, не имеющей параметров, или фрагмента кода, называемой санкам (Ошп1к).
Саик должен вызываться при кажлой ссылке на параметр, передаваемый по имени в вызываемой полпрограмме. Саик вычисляет в соответствующей среде ссылку на полпрограмму, передавшую фактический параметр. Саик связывается со своей средой ссылок в момент вызова, передающего параметр по имени, и возвращает адрес фактического параметра. Если ссылка на параметр является частью некоего выражения, то код ссылки должен содержать необходимое разыменование, чтобы получить значение из ячейки, адрес которой был возвращен с помощью санков. Все это вместе взятое образует очень затратный процесс по сравнению с простой Елово 8. Подпрограммы .