лекции (1998) (Буров), страница 3

2019-09-19СтудИзба

Описание файла

Документ из архива "лекции (1998) (Буров)", который расположен в категории "". Всё это находится в предмете "языки программирования" из 7 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .

Онлайн просмотр документа "лекции (1998) (Буров)"

Текст 3 страницы из документа "лекции (1998) (Буров)"

Конечно, реализация такой абстракции немного отличается - например, выход из процедуры может быть не один (выход при возникновении ошибочной ситуации). Но тем не менее, общая схема такова.

В современных ЯП точка входа - одна, это стало аксиомой для ЯП, начиная с 70х годов. Хотя, старые ЯП (например, Fortran) имели конструкции, которые позволяли «входить» в подпрограмму в различных точках.

Множественные точки выхода - допускаются, как уже было сказано выше. Для этого в современнях ЯП имеется, как правило, оператор RETURN (или аналоги), который завершает выполнение подпрограммы. Множественные точки выхода не противоречат принципу черного ящика (т.к. их всегда можно свести к одной точке).

Другое дело, если бы мы могли организовать точки выхода, как это было возможно в старых ЯП. В том же самом Фортране есть понятие формального параметра-метки. То есть можно передавать метку, на которую возвращалось управление после завершения подпрограммы:

Это безобразие с точки зрения структурного программирования, но тем не менее, программисты пользовались этим свойством, как весьма удобным в некоторых ситуациях. Сейчас такого, конечно же, нет.

Заметим, что схема с подпрограммами - несимметрична. То есть у нас есть главная программа и подпрограмма. Вызываем мы из разных точек, а управление попадает всегда в одну точку:

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

Фактически у нас попеременно выполняется то COR1, то COR2, но в отличии от подпрограмм, управление передается каждый раз не на точку входа COR1 или COR2, а на точку, где сопрограмма была прервана последний раз. И еще - при использовании подпрограмм мы говорим об операторах вызова и возврата, здесь же нельзя провести подобное разделение. Мы имеем оператор передачи управления. Обычно употребляют имена RESUME или TRANSFER.

Сопрограммы могут быть реализованы в языке С через setjump/longjump, нечто подобное присутствовало и в Модула-2, правда, не на базисном уровне, а на уровне библиотеки.

В Модула-2 существует функция TRANSFER( COR1, COR2), параметры COR1 и COR2 имеют тип ADDRESS (указатель «куда-то там», аналог void * в языке C). Зачем нужно два параметра? Очевидно, для того, чтобы запоминать, куда следует возвращаться, каково было состояние процесса в том месте, где мы его прервали. С точки зрения смысла COR1 и COR2 должны иметь тип некоторого контекста, в котором хрянятся регистры, счетчик команд и т.д. Но вместо того, чтобы описывать всю структуру на верхнем уровне, ее скрыли под тип ADDRESS. Чтобы передать управление обратно достаточно вызвать TRANSFER(COR2, COR1).

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

Таким образом, мы увидели, как методом проб и ошибок, рационализацией было упрощено понятие подпрограмм. Современные языки не реализуют сопрограммы на базисном уровне, так как это всегда можно сделать некоторыми расширениями.

На этом мы закончим обсуждение вопроса о передаче управления и обсудим каким образом происходит передача данных в момент вызова подпрограмм.

Передача данных

Наиболее абстрактная схема передачи данных реализована в языке Ada. В Ada все способы передачи данных сведены к трем:

  • in - служат для передачи параметров из главной программы в подчиненную;

  • out - из подчиненной в главную;

  • inout - и туда. и обратно.

Для этого в Ada есть три ключевых слова: IN, OUT, INOUT. Далее мы не должны делать никаких предположений относительно того, как компилятор реализует механизмы передачи тех или иных параметров. Программисту ясно, что IN - это параметры, которые не изменяются после выполнения процедуры, OUT - наоборот изменяются, а INOUT - должны быть определены до входа в подпрограмму и изменяют свое значение после выхода из нее. Это такая общая схема. Конечно, в реальной жизни хотелось бы знать больше о том, каким способом реализуется механизм передачи данных.

Поговорим более подробно.

PROCEDURE A (X: INTEGER; Y: OUT REAL; Z: INOUT T);

По умолчанию, если не указан тип способ передачи параметра, Ada подразумевает IN.

Вообще говоря, существует пять способов передачи параметров:

  1. По значению (IN);

  2. По результату (OUT);

  3. По значению результата;

  4. По ссылке;

  5. По имени;

Заметим, что четвертый и пятый пункты - взгляд немного с другой стороны.

Механизм передачи параметра по значению достаточно прост - для подпрограммы выделяется некоторая область памяти (стек), в который копируется значение фактического параметра, которое в свою очередь и используется процедурой.

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

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

Вполне естественно, что при передаче по результату, класс фактического параметра должен быть достаточно ограничен (понятно, что не все имеет смысл копировать обратно).

Какие же недостатки у первых трех способов передачи параметров? Прежде всего, необходимость постоянного копирования туда-обратно. При больших объемах фактических параметров, это резко снижает производительность. Необходимы другие способы передачи параметров, которые совместимы, прежде всего, с OUT или INOUT.

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

Пусть переменная X - передана по ссылке, тогда при:

X:=5;

A:=X;

происходит разыменование ссылки, то есть в первом случае число «5» кладется в ту ячейку памяти, где расположен фактический параметр X, во втором случае - значение берется из этой же ячейки. Причем все эти действия берет на себя компилятор, программист же работает с X, как с обычной переменной.

Конечно, такой способ дает полный доступ подчиненной программе к параметру. Очевидно, что компилятор должен контролировать корректность обращения к ячейке.

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

Следующий способ передачи параметров, наиболее логичный способ, - по имени. Параметр передается по имени, если он ведет себя точно также, как объект, который соответствует ему во внешней программе. Иначе говоря, передача по имени очень напоминает макроподстановку. Поясним на примере.

CALL A( A, B)

ПРОЦ A(X,Y)

НАЧ

X:=Y+1;

КОНЕЦ

Передача по имени означает, что мы просто будем подставлять вместо X A, а вместо Y - B. То есть получим:

НАЧ

A:=B+1;

КОНЕЦ

Конечно, могут возникать конфликты с локальными именами, но это уже чисто технический вопрос. Главное, что мы получаем полное отождествление формальных и фактических параметров. Также способом передачи по имени мы можем реализовать IN, OUT, INOUT передачу параметров.

Однако, это довольно хитрый способ передачи параметров. Например, на языке Алгол-60 (где можно было передавать параметры по значению и по имени) была известная задача, целью которой было обосновать, что нельзя на Алгол-60 написать процедуру SWAP (X,Y), которая обменивала бы значения двух переменных. Попробуем написать эту процедуру на немного гипотетическом языке:

ПРОЦ SWAP(X,Y)

ПЕР Т;

НАЧ

T:=X;

X:=Y;

Y:=T;

КОНЕЦ

Заметим, что при вызове SWAP (I, Z[I]) наша процедура будет работать некорректно, если используется передача параметров по имени, хотя вызов SWAP (Z[I], I) , будет абсолютно корректнен.

Но, вообще говоря, передача параметров по имени является самым гибким способом.

В каких языках имеет смысл организовывать передачу параметров по имени? Прежде всего, в динамических языках. Например, в Lisp процесс отождествления параметров идет по имени. И позже, когда мы будем подробнее рассматривать эту схему, мы заметим, что никаких дополнительных расходов не будет, так как в Lisp нет понятия локальной памяти.

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

Но для традиционных ЯП такой способ менее пригоден.

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

В языке С есть только один способ передачи параметров, а именно, по значению. Тут есть противоречие - ведь по значению могут передаваться только IN параметры. Каким же образом обеспечить OUT и INOUT параметры? Разработчики С вышли из этой ситуации с помощью типа указателей. Таким образом мы можем «руками» организовать передачу по ссылке.

Функция SWAP будет выглядеть так:

void SWAP (int *x, int *y)

{

int t;

t=*x;

*x=*y;

*y=t;

};

int a,b;

swap (&a, &b)

Эта программа будет работать так как надо. Заметим, что те действия (операции разыменования), которые, например, компилятор Pascal делает за нас, в данном случае программист реализует явно.

В Pascal реализованы оба способа передачи параметров - как по ссылке, так и по значению. Авторы С ограничились только одним - по значению. Чем они руководствовались? Очевидно, что указывание программистом явно операций разыменования и взятия адреса не облегчает действий ни программисту, ни компилятору, даже наоборот - несколько усложняет.

Это пример авторской позиции, когда что-то хочется, но это «хочется» начинает чему-то мешать. Чему помешало введение второго способа? Мы ответим на этот вопрос чуть позже, когда будем просматривать эволюцию С. Ведь впоследствии С перерос в C++, который существенно расширяет своего предка. Но, заметим, что базис C++ отличается от базиса С только одним новым типом - типом «ссылка ». А именно, в C++ появилось понятие ссылочного типа:

int &x;

Страуструп говорит, что ссылка - это полный аналог имени. Однако не следует путать это с передачей параметра по имени. Если бы это было так, то мы получили бы чистую передачу по имени.

В C++ ссылка вычисляется только один раз при инициализации.

Пусть у нас есть:

{ int a;

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