Процедуры
Внутренние переменные
Внутренние переменные доступны и используются внутри процедур.
Внутренние переменные получившие инициализацию являются статическими, т.е. память выделяется на этапе компиляции (неявно обладают атрибутом static).
Атрибут automatic устанавливает переменные автоматическими, т.е. память выделяется во время работы программы.
program static_var call sub() ! M = 1 call sub() ! M = 2 call sub() ! M = 3 end subroutine sub() integer :: M = 0 M = M + 1 write(*,*) M end subroutine sub |
program static_var call sub() ! M = 1 call sub() ! M = 1 call sub() ! M = 1 end subroutine sub() integer , automatic :: M M = 0 M = M + 1 write(*,*) M end subroutine sub |
Передача параметров
Формальные параметры
- входные, intent(in)
- выходные, intent(out)
- входные/выходные, intent(inout)
subroutine sub(a,b,c) integer, intent(in) :: a real, intent(out) :: b character, intent(inout) :: c ... end subroutine sub
По умолчанию все параметры имеют атрибут inout, т.к. передаются по ссылке.
Вид связи intent(in)
Принимают значение от соответствующего фактического параметра и не могут изменяться при выполнении процедуры.
Соответствующими фактическими параметрами могут быть выражения, переменные, значения, константы.
program param_in call sub(100) end subroutine sub(a) integer, intent(in) :: a ! входной параметр ... end subroutine sub
Вид связи intent(out)
Параметры передают свое значение соответствующему фактическому параметру и предназначены для вывода данных из процедуры.
Соответствующий фактический параметр должен быть переменной.
program param_out call sub(100) ! ошибка, ожидалась переменная end subroutine sub(a) integer, intent(out) :: a ! выходной параметр ... end subroutine sub
Вид связи intent(inout)
Параметры могут как принимать значения от фактического параметра, так и передавать данные в фактический параметр.
Соответствующие фактические параметры должны быть переменными.
program param_inout integer :: q = 80 call sub(q) end subroutine sub(a) integer, intent(inout) :: a ! входной/выходной ... ! параметр end subroutine sub
Optional параметры
Атрибут optional устанавливает формальные параметры необязательными.
Функция present проверяет присутствие необязательного параметра при вызове процедуры.
При отсутствии проверки функцией present возможны ошибки выполнения для параметров с видом связи intent(out, inout).
Процедура должна иметь явный интерфейс.
Optional параметры
program param_in real res res = logarithm(144.0,base = 12.0) write(*,*) res CONTAINS real function logarithm(a, base) real, intent(in) :: a real, intent(in), optional :: base if (present(base)) then logarithm = log(a)/log(base) else logarithm = log10(a) end if end function logarithm END
Область видимости
Объекты1Объекты – переменные, типы данных, внутренние процедуры (для головной программы или внешней процедуры) описанные в головной программе доступны во внутренних процедурах, недоступны во внешних.
Объекты описанные во внутренней, внешней процедурах доступны только в них самих.
При совпадении имен объектов головной программы и внутренней или внешней процедур, объекты являются разными.
program array integer, parameter :: M = 10 integer :: A(M) = [2,4,6,8,9,1,1,1,1,1] call PrintArray() contains subroutine PrintArray() ! нет формальных параметров integer k ! доступ к массиву A do k = 1,M ! из головной программы write(*,"(i6,\)") A(k) end do write(*,*) end subroutine PrintArray END
Оператор interface
Почему при компиляции выдаётся ошибка?
program question write(*,*) middle(3.0,2.0) END real function middle(a,b) real a,b middle = (a+b)/2 end function middle
По умолчанию тип функции middle – целый. Функция объявлена как вещественная, но головная программа об этом "не знает".
Как указать головной программе про тип функции middle?
Определяет явно заданный интерфейс.
Используется для внешних процедур.
Внутренние процедуры обладают явно заданным интерфейсом.
interface тип имя_функции(формальные параметры) тип формальных параметров конец описания функции end interface
Исправленная версия программы
program question interface real function middle(a,b) real a,b end function middle end interface write(*,*) middle(3.0,2.0) END real function middle(a,b) real a,b middle = (a+b)/2 end function middle