Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
современный фортран , Бортеньев.pdf
Скачиваний:
242
Добавлен:
26.03.2015
Размер:
2.34 Mб
Скачать
! Формируем массив c1 ! Формируем массив c2 ! -3 4 -4 ! -4 5 -5

О. В. Бартеньев. Современный ФОРТРАН

8.11. Параметры процедур

Обмен данными между процедурой и вызывающей программной единицей может быть выполнен через параметры процедуры.

Параметры, используемые при вызове процедуры, называются

фактическими.

Параметры, используемые в процедуре, называются формальными.

Пример. Сформировать вектор c1 из элементов вектора a, которых нет в векторе b1. Затем сформировать вектор c2 из элементов вектора a, которых нет в векторе b2. Формирование массивов выполним в подпрограмме fobc.

program part

integer, parameter :: na = 10, nb1 = 5, nb2 = 7 integer :: a(na) = (/ 1, -1, 2, -2, 3, -3, 4, -4, 5, -5 /) integer :: b1(nb1) = (/ 1, -1, 2, -2, 3 /)

integer :: b2(nb2) = (/ 1, -1, 2, -2, 3, -3, 4 /) integer c1(na), c2(na), nc1, nc2

call fobc(a, na, b1, nb1, c1, nc1) call fobc(a, na, b2, nb2, c2, nc2)

write(*, *) c1(:nc1) 5 -5 write(*, *) c2(:nc2)

end program

subroutine fobc(a, na, b, nb, c, nc)

 

integer na, nb, a(na), b(nb)

! Входные формальные параметры

integer c(na), nc

! Выходные формальные параметры

integer i, j, va

 

nc = 0

! Число элементов в формируемом массиве

loop_a: do i = 1, na

! Имя DO-конструкции использует

va = a(i)

! оператор CYCLE loop_a

do j = 1, nb

 

if( va == b(j) ) cycle loop_a

 

end do

 

nc = nc + 1

 

c(nc) = va

 

end do loop_a

 

end subroutine fobc

 

В операторе CALL fobc присутствуют фактические параметры. Тогда как присутствующие в операторе SUBROUTINE fobc параметры a, na, bc

и m являются формальными.

8.11.1. Соответствие фактических и формальных параметров

При вызове процедуры между фактическими и формальными параметрами устанавливается соответствие (формальные параметры ассоциируются с соответствующими фактическими). Так, в нашем примере при первом вызове подпрограммы fobc фактическому параметру a

236

8. Программные единицы

соответствует формальный параметр a, фактическому параметру b1 - формальный параметр b и т. д. Типы соответствующих параметров совпадают. Как видно из примера, имена соответствующих фактических и формальных параметров могут различаться.

В нашем примере скорее всего фактический и соответствующий ему формальный параметр будут адресовать одну и ту же область памяти. Правда, это справедливо не во всех случаях. Так, если фактическим параметром является сечение массива, то при вызове процедуры компилятор создаст его копию, которую и будет адресовать формальный параметр. При выходе из процедуры (если параметр имеет вид связи OUT или INOUT) произойдет обратная передача данных из копии в сечениепараметр.

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

Формальными параметрами могут быть переменные (полные объекты), процедуры и звездочка (*).

Фактические и формальные параметры могут иметь атрибуты, например

POINTER или TARGET.

Устанавливая соответствие между фактическими и формальными параметрами, следует придерживаться приведенных в табл. 8.2 правил.

Таблица 8.2. Фактические и формальные параметры

 

Фактический параметр

Формальный параметр

 

 

 

 

Скалярное выражение

Скалярная переменная

 

 

 

 

Нескалярное выражение (массив, сечение массива...)

Массив

 

 

 

 

Процедура

Процедура

 

 

 

 

*Метка (только для подпрограмм)

* (звездочка)

 

 

 

 

 

 

Замечания:

1.Если формальный параметр является ссылкой, то и соответствующий фактический параметр тоже должен быть ссылкой.

2.Если фактическим параметром является строка, то формальным параметром может быть строка, перенимающая длину (разд. 3.8.2).

3.Если фактическим параметром является элемент массива, то соответствующим формальным параметром может быть массив (разд. 4.9.1).

237

О. В. Бартеньев. Современный ФОРТРАН

4.Если фактическим параметром является массив, то формальным параметром может быть массив заданной формы, или перенимающий форму массив, или перенимающий размер массив (разд. 4.9).

5.Если фактический параметр является внешней процедурой, то он должен иметь атрибут EXTERNAL. Если же фактический параметр является встроенной процедурой, то он должен быть объявлен с атрибутом INTRINSIC.

8.11.2. Вид связи параметра

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

В подпрограмме fobc (разд. 8.11) формальные параметры a, na, b и nb являются входными. Параметры c и nc – выходными, т. е. их значения определяются в процедуре и потом уже используются в вызывающей программной единице. Такое разделение формальных параметров примера на входные/выходные мы выполнили, исходя из совершаемых программой действий. На самом деле вид связи формального параметра можно задать явно, использовав атрибут INTENT, например:

subroutine fobc(a, na, b, nb, c, nc) integer, intent(in) na, nb, a(na), b(nb) integer, intent(out) c(na), nc

integer i, j, va

Для задания атрибута INTENT может быть применен оператор INTENT:

subroutine fobc(a, na, b, nb, c, nc)

integer na, nb, nc, a(na), b(nb), c(na), i, j, va intent(in) na, nb, a, b

intent(out) c, nc

Синтаксис оператора INTENT: INTENT (spec) [::] vname

Синтаксис атрибута INTENT: type-spec, INTENT (spec) [, attrs] :: vname

spec - вид связи формального параметра, spec может принимать одно из трех значений:

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

238

8. Программные единицы

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

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

vname - разделенные запятыми имена формальных параметров. type-spec - спецификация любого типа данных.

attrs - список иных атрибутов формального параметра.

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

real :: length, x = 3.0, y = 4.0, r

 

r = length(3.0, 4.0)

! Этот вызов ошибочен

r = length(x, y)

! Этот вызов допустим

end

 

real function length(x, y)

! Первый вызов ошибочен, поскольку

real x, y

! формальные параметры x и y

call square(x, y)

! переопределяются в подпрограмме square

length = sqrt(x + y)

 

end function

 

subroutine square(x1, y1)

 

real, intent(inout) :: x1, y1

 

x1 = x1 * x1

 

y1 = y1 * y1

 

end subroutine

 

Если формальный параметр имеет вид связи IN, то он не должен быть использован в качестве фактического параметра, ассоциируемого с формальным параметром, вид связи которого OUT или INOUT. Так, в предыдущем примере формальные параметры x, y функции length не должны иметь вид связи IN.

Если функция задает перегружаемую операцию, то формальные параметры обязаны иметь вид связи IN. Если подпрограмма определяет задаваемое присваивание, то первый ее формальный параметр должен иметь вид связи OUT или INOUT, а второй - IN.

Недопустимо использование атрибута INTENT:

для формальных параметров с атрибутом POINTER;

239