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

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

где a - необязательный формальный параметр. Функция возвращает .TRUE., если формальный параметр a ассоциирован с фактическим, и .FALSE. - в противном случае.

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

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

ВФортране это правило может быть нарушено, если использовать при вызове процедуры параметры с ключевыми словами. Ключевые слова - это имена формальных параметров, присвоенные им в интерфейсном блоке

Например, допустимы вызовы функции npe:

result = npe(sig = 1, array = a, me = m) result = npe(a, sig = 1, me = m)

result = npe(a, sig = 1)

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

Однако позиционные параметры не могут появляться в списке фактических параметров после первого появления параметра с ключевым словом. Так, ошибочен вызов

result = npe(array = a, m, 1)

8.11.5. Ограничения на фактические параметры

Стандарт устанавливает два ограничения на фактические параметры:

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

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

244

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

Для иллюстрации ограничений рассмотрим пример:

integer a(10) /10*2/, x, xx, y /2/ common /cb/ x, xx character(10) st /'??????????'/

call rest1(x, xx, a(1:7), a(4:10)) ! Согласно ограничению 1 в rest1 call rest2(y, st(3:7)) ! нельзя менять значение a(4:7) print *, x, xx, a(5), y, ' ', st

contains

 

subroutine rest2(y2, st2)

 

integer y2

 

character(*) st2

 

y2 = 4

! Верно

y = 6

! Нарушено ограничение 2

st2 = '&&&&&'

! Верно

st = '##########'

! Нарушено ограничение 2

end subroutine rest2

 

end

 

subroutine rest1(x2, xx2, a, a2)

 

integer x2, xx2, a(*), a2(*)

 

common /cb/ x, xx

 

x = 1

! Нарушено ограничение 1

x2 = 11

! Верно

xx2 = 3

! Верно

xx = 33

! Нарушено ограничение 1

a(1:3) = 22

! Верно

a2(5:7) = 44

! Верно

a(4:7) = 5

! Нарушено ограничение 1

a2(1:4) = 7

! Нарушено ограничение 1

end

 

Хотя пример насыщен нарушениями, CVF и FPS не выдадут ни одного сообщения или предупреждения об ошибке. Однако это совсем не означает, что программа отработает правильно. В общем случае результат непредсказуем. Это видно, в частности, из выведенных результатов:

CVF:

11 1107558400

7

6 ##########

FPS:

11 1107558400

5

6 ##########

Аналогичным образом если переменная, например xx, доступна процедуре rest1 через модуль и одновременно ассоциируется с формальным параметром xx2 этой процедуры, то будет нарушено ограничение 1 при попытке изменить значение xx в процедуре rest1.

8.11.6. Запрещенные побочные эффекты

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

245

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

logical g, flo

 

 

 

real :: x = 5.0, y = 4.0, z = 7.0

 

 

 

g = x > y .or. flo(z)

 

 

 

print *, g, z

! FPS:

T

7.0000

end

! CVF:

T

100.0000

logical function flo(z) z = 100

flo = .true. end function flo

в FPS не будет выполнено обращение к логической функции flo. В соответствии с положениями стандарта значение переменной z должно после вычисления выражения стать неопределенным. Хотя в FPS переменная z и сохранит свое значение, а в CVF изменит, совершенно очевидно, что следует избегать подобных вызовов функции. Действительно, если бы значение x было равно 3.0, то после вычисления выражения в FPS мы получили бы совсем иное значение для z - число 100.0.

Другой пример, когда стандарт допускает неполное вычисление выражения:

character(len = 2) :: stre, st1 = 'd1', st2 = 'd2'

!stfun - символьная функция. Стандарт разрешает не выполнять вызов stfun,

!поскольку длина результата stre равна st1, и он полностью определяется первым

!операндом выражения st1 // stfun(st2)

stre = st1 // stfun(st2) print *, st2

contains

character(2) function stfun(st2) character(*) st2

st2 = 'd3' stfun = 'd4'

end function stfun end

Заметим, однако, что и CVF и FPS обратятся к функции stfun и переменная st2 получит значение 'd3'.

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

d = max(dist(p, q), dist(q, r))

функция dist не должна переопределять переменную q.

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

246