лекции (2010) (by Ульянов Алексей_ Лихогруд Николай_ Сергеев Николай) (1160852), страница 8
Текст из файла (страница 8)
Подпрограммап5.1 Потоки управления – подпрограммы и сопрограммыУправление входит через заголовок в блоке и возвращается в точку вызове, после выполнения тела.CALLER – вызывающий подпрограмму(надпрограмма)CALLEE – вызываемая подпрограмма….Call…..Call…...…...…..….SUBROUTINE – подпрограммаCOROUTINE – сопрограмма//PP//P….….….….Неравенствоcall P//P//PP….….….….resume PPresume PРавенство….Также нарушение априорного порядка выполнения команд может происходить при генерации исключений.Впервые механизм сопрограмм был придуман для компилятора COBOL.
Вспомните задание по Си++ в 4-мсеместре, где нужно было написать транслятор модельного языка:Лексический анализатор, Синтаксический анализатор, Генератор кода – всё это сопрограммы.Сопрограммы – фактически квазипараллельные процессы.Модула-2Вызов сопрограммы аналогичен длинному переходу на некоторый абстрактный адрес, по которомунаходится команда сопрограммы, с которой нужно начать выполнение. Но, помимо этого, нужно ещё как-тозапомнить адрес возврата и другую служебную информацию, передать входные параметры, наследуетсячасть контекста.
Для этой цели Вирт в своём языке Модула-2 ввёл тип данных ADDRESS (то же самое, что и«void *»).Этот тип данных является потенциальной дырой в системе безопасности, т.к. любой указатель «Т *»автоматически приводится к «void *», и возможно обратное явное преобразование «Т *» = (Т *)«void *». ДляВирта было неприятной неожиданность то, что программисты часто использовали тип данных ADDRESS.Строгость типизации зависит от возможностей преобразования.Типы – непересекающиеся области эквивалентности, определяемые операциями на объектами этихобластей.Итак, в Модуле-2 вызов сопрограммы имеет такой вид:NEWPROCESS(P, C,N);Где P – процедура без параметров типа PROCEDURE, который является встроенным, C – переменная типаADDRESS.
N - размер области для «запоминания» информации. Область начинается с адреса CPROCEDURE NEWPROCESS(P : PROCEDURE; VAR C : ADDRESS; N : INTEGER);Передача управления от одного процесса другому на уровне сопpогpамм осуществляется процедурой"Передать управление от процесса P1 процессу P2". В Модуле-2 эта процедура выглядела какPROCEDURE TRANSFER(VAR P1,P2 : ADDRESS);При этом в переменную P1 записывается запись реактивации этого процесса, а значение переменной P2определяет запись активации процесса P2.RESUME; – оператор языка.Маленькое замечание:Изначально Вирт вместо ADDRESS использовал тип COROUTINE, теперь понятнее? Тип COROUTINE был похожне структуру.В современных языках сопрограммы трансформировались в понятие потока..Net ThreadКвазипараллельный потокC# 2.0:foreach(T x in C)Тип T должен реализовывать интерфейс IEnumerable.
Этот интерфейс содержит метод GetEnumerator(),который возвращает объект некоторого типа, который должен реализовывать интерфейс IEnumerator сосвойствами Current,методом Reset и методом bool MoveNext(). Любой класс, поддерживающий интерфейсIEnumerable должен содержать класс, поддерживающий IEnumerator.yield-операторы в C# 2.0:yield return <expression>;yield break;Итератор – процесс(сопрограмма), выдающий последовательно очередные элементы коллекции тогда, когдаони понадобятся. yield-оператор используется в блоке итератора для предоставления значения объектаперечислителя или для сообщения о конце итерации.
Т.е. это не простой «return» или «break», а оператор,совмещающий в себе дополнительно работу по переходу между сопрограммами (от процесса-итератора восновной процесс). Выражение expression вычисляется и возвращается в виде значения объектуперечислителя; выражение expression должно неявно преобразовываться в тип результата итератора.ublic class List{//using System.Collections;public static IEnumerable Power(int number, int exponent){int counter = 0;int result = 1;while (counter++ < exponent){result = result * number;yield return result;}}static void Main(){// Display powers of 2 up to the exponent 8:foreach (int i in Power(2, 8)){Console.Write("{0} ", i);}}}/* Output:2 4 8 16 32 64 128 256 */Генеральная линия развития C# - добавление элементов функционального программированияп.5.2 Потоки данных в подпрограммах••Через глобальные данныеЧерез параметрыПобочный эффект действия процедур и функций – изменение значений глобальных переменных и данных, атак же модификация данных, глобальных по отношению к самой процедуре\функции.Глобальная переменная – переменная, которая видна вездеint aВозможен конфликтсвязейP1P2P1P4В объектно-ориентированной парадигме:Глобальное, поотношению к данномуобъекту , пространствоимёнобъектЧлены-данныеСначала «i» ищется в телефункции, потом в членахданнных, и только после этоговне объекта//Методы…void f(){ … ;Виды формальных параметров(семантика):•••Входные (in) – должны быть определены до входаВыходные (out) – должны быть определены к моменту выходаВх/Вых(InOut) – и то и другоеСпособы передачиСпособ передачи – способ связывания фактических и формальных параметров:По значению (семантика - in)По результату (семантика – out)По значению/результату (семантика – InOut)По адресу(по ссылке) (семантика - любая)По имени•••••Ада83:Квалификаторы: in, out, inoutProcedure P(int X:T;inout Y:T;out Z:T);X может быть выражением типа T.
Компилятор может вставлять квазистатические проверки. Эффектпроцедуры – модификация Y и Z. Каков способ передачи определяет компилятор( что не есть хорошо, т.к.различные компиляторы в одной и той же ситуации могут выбрать разные способы передачи, что приведёт кразличной работе программ).Пользователь определяет семантику использования.Запись активации…..……Место для формальных параметровФормальные параметры – те, которые объявлены в заголовке подпрограммы и используются в теле.Большинство ЯП переменные, которые объявлены в заголовке, считают частью тела.Фактические параметры – те, которые передаются в подпрограмму при её вызове.При вызове подпрограммы фактические параметры, указанные в команде вызова, становятся значениямисоответствующих формальных параметров, чем и обеспечивается передача данных в подпрограмму.Способ передачиПо значениюСемантикаinПо результатуOutПо значению и результатуinoutЧто делаетсяПри вызове подпрограммы фактические параметрыкопируются в Запись АктивацаииПри выходе из подпрограммы из записи активацииформальные параметры копируются в фактическиеПри вызове подпрограммы фактические параметрыкопируются в Запись АктивацаииПо Адресу••ЛюбаяПри выходе из подпрограммы из записи активацииформальные параметры обратно копируются вфактическиеПри передаче по Адресу в Запись активациикопируется адрес фактического параметры.Именование и разыменование происходятавтоматическиВ Фортране обычно параметры передаются по адресу, но когда передаётся простой объект данных,чтобы не происходило лишних операций разыменования, можно передавать «по значению ирезультату»( /<параметр>/)В Аде-83 способ передачи зависел от компилятора, т.е.
компилятор сам выбирал способ передачи взависимости от ситуации. Пример программы, в которой это важно:Procedure P(inout X : T; inout Y : T)X := <newvalueX>;<возбуждение исключения>Y := <newvalueY>;End P;….P(a,a);Предположим, что оно не обрабатывается. Тогда запись активации пропадает. Значит, если была передача поссылке, то значение «а» изменится, а если по значению и результату, то не изменится, т.к. копировать в «а»будет нечего.Энтропия – явление, при котором программа может выдавать различные результаты при одних и тех жеисходных данных. Если в программе есть энтропия, то это очень плохо.
Очевидно, что при программированиина Ада риск энтропии значительно повышается, т.к. не известно какой способ передачи выберет в этот разкомпилятор.•••В Ада-95 – по значению, по ссылкеВ Си – не определяется семантика использования. Способ передачи только по значениюВ Си++ – по значению, по адресу (ссылке). Контроль семантики: in – ссылка константная, out, inout – неконстантнаяvoid f( T &); //Компилятор считает, что f будет менять значение => константный объект//передавать нельзяЭто указание для компилятора, чтобы он следил за соблюдением семантикиclass X{void f(); //неконстантная функция;}……..const X a;//X * const this; внутри методовa.f();// ошибка!!class X{void f() const; //константная функция;}……..const X a;//X * const this; внутри методовa.f();// Правильно!!•С#, Javavoid f( T x) {….;}……T a; // a – ссылка, если Т – объектf(a); // передаётся ссылкаОба языка поддерживают идею примитивных типов (которые в C# являются подмножеством типов-значений— value types), и оба для трансляции примитивных типов в объектные обеспечивают их автоматическое«заворачивание» в объекты (boxing) и «разворачивание» (unboxing) (в Java — начиная с версии 1.5).object – предок всех классов.
=> Объект любого класса неявно приводится к типу object.object o;int i;o = i;i = o; // ошибка!Автоупаковка, Автораспаковка:o = i; // o = new Integer(i) – Java// o = new Int32(i) – C#Так что если функция объявляется как void f(object o), то в неё можно передавать любой объект( дляпримитивных типов будет производится автоупраковка\распаковка)• Java:В Java параметры метода передаются только по значению, но поскольку для экземпляров классов передаётсяссылка, ничто не мешает изменить в методе экземпляр, переданный через параметр.
Структур в Java нет.Передача объектов примитивных типов в методы «как по ссылке» выполняется через классы-обёртки:void f(Integer X){…X = ….; }…..int i = 1;Integer px = new Integer(i);f(px);i = px;Integer – класс-обёртка для примитивного типа «int». Суть способа – преобразовать объект примитивноготипа в объект класса и работать внутри функции с объектом класса.• C#для C# создана более развитая терминология:Тип-значение(value type) – тип, объекты которого передаются по значению. Если где-то нужен объект такоготипа, то отводится место под сам объект.
типами-значениями являются простые(примитивные) типы данных иструктурыРеференциальный тип – тип, объекты которого передаются по ссылке. Если где-то нужен объект такого типа,то отводится место под адрес. Референциальными типами являются классы(любой массив – наследниккласса Array, строка это объект класса String, и т.д.)В принципе, в C# можно передавать объекты простых типов в функции с помощью классов-обрёток, но C#также поддерживает явное описание передачи параметров по ссылке – ключевые слова ref и out.