Главная страница
Навигация по странице:

  • 8.8. Оператор USE Доступ к модулю выполняется посредством использования оператора USE. Если, например, задан оператор 226

  • 8.9. Атрибуты PUBLIC и PRIVATE

  • 8.10. Операторы заголовка процедур

  • современный фортран , Бортеньев. О. В. Бартеньев Современный Фортран


    Скачать 2.24 Mb.
    НазваниеО. В. Бартеньев Современный Фортран
    Анкорсовременный фортран , Бортеньев.pdf
    Дата28.05.2018
    Размер2.24 Mb.
    Формат файлаpdf
    Имя файласовременный фортран , Бортеньев.pdf
    ТипДокументы
    #19729
    страница25 из 49
    1   ...   21   22   23   24   25   26   27   28   ...   49
    224

    8. Программные единицы subroutine smod(d) integer d, c2 /1/ d = 2 b = 1 + c call smod2(d) print *, 'smod :', d, b contains subroutine smod2(d)
    ! Подпрограмма smod2 доступна integer d
    ! только подпрограмме smod print *, 'smod2 :', d, b d = d + 1 b = b + c2
    ! c2 доступна в smod2 благодаря ассоциированию end subroutine smod2
    ! через носитель end subroutine smod end module testmod program prom use testmod
    ! Ссылка на модуль TESTMOD print *, 'prom_1:', a, b
    ! a и b доступны в prom и osub благодаря call smod(a)
    ! use-ассоциированию print *, 'prom_2:', a, b call osub( ) print *, 'prom_3:', a, b end program prom subroutine osub( ) use testmod print *, 'osub :', a, b a = 4 b = 4 end subroutine osub
    Результат:
    prom_1: 1 1 smod2 :
    2 2 smod :
    3 3 prom_2: 3 3 osub :
    3 3 prom_3: 4 4
    Объявленные в модуле TESTMOD переменные a и b являются глобальными в том смысле, что они видны в любом ссылающемся на модуль программном компоненте. Такой способ передачи данных называется use-ассоциированием.
    Также значения переменных a, b и с, объявленные в модуле TESTMOD, известны модульной подпрограмме smod и ее внутренней подпрограмме
    smod2. Такой способ передачи данных называется ассоциированием через
    носитель. Благодаря ассоциированию через носитель внутренняя
    225

    О. В. Бартеньев. Современный ФОРТРАН
    подпрограмма
    smod2, носителем которой является модульная подпрограмма smod, имеет доступ к локальной переменной c2 подпрограммы smod.
    Кроме того, в примере главная программа prom, модульная подпрограмма
    smod, внутренняя подпрограмма smod2 обмениваются данными через параметр
    d. Такая передача данных называется ассоциированием параметров.
    Рассмотренное use-ассоциирование позволяет передавать не только данные, но и статус размещаемых массивов (разд. 4.8.2) и ссылок.
    Например: module mod integer, pointer :: a(:) end module program tpo use mod integer, parameter :: m = 4, n = 5 integer, target :: b(5) = 5 a => b
    ! Прикрепляем ссылку к адресату b call shost( )
    ! Статус ссылки будет известен в shost print *, a
    ! 3 3 3 end program subroutine shost( ) use mod integer, target :: c(3) = 3 print *, associated(a)
    ! T print *, a
    ! 5 5 5 5 5 a => c end subroutine shost
    Исходный текст модуля может быть размещен в том же файле, в котором размещены и использующие его программные единицы. При этом его текст должен предшествовать ссылкам на модуль. Можно разместить модуль в отдельном файле, например модуль TESTMOD (один или вместе с другими модулями) может быть размещен в файле mofil.f90. При компиляции этого файла (файл должен быть включен в проект) для каждого его модуля будет создан файл, имеющий имя модуля и расширение MOD.
    Так, для модуля TESTMOD будет создан файл testmod.mod. При работе с откомпилированными файлами модулей присутствие исходных текстов модулей в проекте необязательно, но компилятору должны быть известны пути к откомпилированным файлам или к содержащим эти файлы библиотекам.
    8.8. Оператор USE
    Доступ к модулю выполняется посредством использования оператора
    USE. Если, например, задан оператор
    226

    8. Программные единицы
    USE TESTMOD то программная единица получает доступ ко всем не имеющим атрибута
    PRIVATE объявленным в разделе описания модуля объектам данных и модульным процедурам модуля. Причем все объекты модуля известны в использующей его программной единице под теми именами, которые они имеют в модуле.
    В то же время оператор USE позволяет:

    ограничить доступ к объектам модуля за счет применения параметра
    ONLY;

    использовать в программной единице для объектов модуля другие имена.
    Например, на модуль TESTMOD (разд. 8.7) можно сослаться так: use testmod, only : a, smod или так: program prom use testmod, va => a, prosub => smod print *, 'prom_1:', va, b call prosub(va) call osub( ) end program prom
    В первом случае в использующей модуль TESTMOD программной единице будут видны только переменная a модуля и его подпрограмма
    smod. Во втором случае в результате переименования переменная a модуля
    TESTMOD будет доступна в prom под именем va, а модульная подпрограмма smod - под именем prosub. Глобальная переменная b модуля будет доступна под ее собственным именем. Механизм взаимодействия модуля и использующей его программной единицы, разумеется, сохранится.
    Переименование и ограничение доступа посредством ONLY применяется в основном для предотвращения конфликта имен. Например, если программная единица использует два модуля, в которых есть одноименные глобальные объекты, то для предотвращения конфликта по крайней мере один из этих объектов следует использовать под другим именем. Если же, например, имя глобального объекта модуля конфликтует с именем локального объекта использующей модуль программной единицы и к тому же этот объект модуля в этой программной единице не применяется, то конфликт можно преодолеть, ограничив опцией ONLY доступ к этому объекту.
    Дадим теперь общее представление двух форм оператора USE:
    USE имя модуля [, список переименований]
    USE имя модуля, ONLY: [only-список]
    Список переименований содержит переименования глобальных объектов модуля. Каждый элемент списка имеет вид
    227

    О. В. Бартеньев. Современный ФОРТРАН
    local-name => use-name
    и означает, что объект модуля c именем use-name будет доступен в использующей модуль программной единице под именем local-name. В общем случае можно для одного use-name использовать несколько разных
    local-name, например: use testmod, prosub => smod, prosub2 => smod
    only-список ограничивает доступ к глобальным объектам модуля.
    Элементом списка может быть любое глобальное имя, в том числе задаваемый оператор, задаваемое присваивание, родовое имя, имя объявленного в модуле производного типа данных. Например: module mymod type point
    ! Объявляем в модуле производный тип данных point real(4) :: x, y, z end type point end module mymod program t2 use mymod
    ! Теперь тип данных point доступен в t2 type(point) :: pt
    ! Объявляем переменную pt типа point
    pt = point(1.0, 2.0, 3.0)
    ! Даем переменную pt типа point начальные значения print *, pt
    ! 1.000000 2.000000 3.000000 end program t2
    Также only-список может включать элемент вида
    [local name =>] use-name
    Находящиеся в only-списке объекты модуля не могут иметь атрибут
    PRIVATE. Если опция ONLY задана, то в использующей модуль программной единице доступны только размещенные в only-списке объекты модуля.
    Программная единица может содержать более одного оператора USE для любого модуля, например: use testmod, only : va => a, b use testmod, only : prosub => smod
    В этом случае only-списки сцепляются в один only-список. Если же хотя бы один оператор USE использован без опции ONLY, то использующей модуль программной единице будут доступны все глобальные объекты модуля, а присутствующие переименования в списках переименований и
    only-списках сцепляются в единый список переименований.
    Пример: module mymod real :: a = 5.0 end module mymod
    228

    8. Программные единицы program t3 use mymod, a2 =>a
    ! Теперь переменная а модуля MYMOD доступна в t3 под именем и a2 print *, a, a2
    ! 0.000000 5.000000
    ! Переменную a можно использовать в t3 как локальную end program t3
    Все используемые при переименовании локальные имена должны отличаться друг от друга и от локальных имен использующей модуль программной единицы. Локальные имена программной единицы должны отличаться от глобальных имен модулей, на которые в ней имеются ссылки.
    Например, следующий код: module mymod real :: a = 5.0 contains subroutine b(d) real d d = 4.5 end subroutine b end module mymod program t4 use mymod b = 1.2
    ! Глобальное имя b уже использовано в MYMOD end program t4
    ! как имя подпрограммы вызовет ошибку компиляции: Error: This name has already been used as an external subroutine name. [B] b = 1.2. Если же в t4 добавить объявление real(4) b то дополнительно возникнет ошибка: Error: The attributes of this name con- flict with those made accessible by a USE statement. [B] real(4) b.
    Избежать ошибки можно, во-первых, удалив из t4 ссылку use mymod, во- вторых, выполнив переименование, например use mymod, b2 => b, и, в-третьих, изменив имя локальной переменной b главной программы t4, например на b3.
    Один и тот же глобальный объект модуля может быть доступен под несколькими локальными именами. Это достигается либо за счет его неоднократного использования в списке переименований, либо, например, так: module a real s, t end module a module b use a, bs => s
    229

    О. В. Бартеньев. Современный ФОРТРАН
    end module b subroutine c
    ! Переменная s модуля a доступна подпрограмме c use a
    ! под своим настоящим именем s и именем bs use b end subroutine c
    Имена глобальных объектов используемых программной единицей модулей могут дублироваться, если:

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

    глобальные объекты, не являющиеся родовыми интерфейсами, доступны программной единице, но в ней не используются.
    Если операторы USE содержатся в модуле, то все выбранные объекты рассматриваются как объекты самого модуля. Им можно дать атрибуты
    PRIVATE или PUBLIC как явно, так и по умолчанию. Задавать какие-либо иные атрибуты у выбранных объектов нельзя, но их можно включать в одну или более namelist-групп. Однако нельзя задать атрибут PUBLIC объекту включаемого модуля, если в последнем объект имеет атрибут PRIVATE.
    Пример. Выполняется переименование имен производных типов данных. module geometry
    ! Определения производных типов данных type square real side integer border end type type circle real radius integer border end type end module program test
    ! Переименуем имена типов данных модуля для локального использования use geometry, lsquare => square, lcircle => circle type(lsquare) s1, s2
    ! Используем новые имена при объявлении type(lcircle) c1, c2, c3
    ! переменных
    8.9. Атрибуты PUBLIC и PRIVATE
    Атрибуты PUBLIC и PRIVATE могут быть даны только объектам модуля. Атрибут PUBLIC указывает, что объект модуля может быть доступен в результате use-ассоциирования в использующих модуль
    230

    8. Программные единицы программных единицах. Напротив, если объект модуля имеет атрибут
    PRIVATE, то он может быть использован только внутри модуля. Задание атрибутов может быть выполнено как отдельным оператором, так и при объявлении типа:
    PUBLIC | PRIVATE [[::] объекты модуля]
    type-spec, PUBLIC | PRIVATE [, атрибуты] :: объекты модуля
    Объекты модуля могут включать имена переменных, констант, процедур, namelist-групп, производных типов и родовых описаний.
    type-spec - оператор объявления встроенного или производного типа данных.
    По умолчанию объекты модуля имеют атрибут PUBLIC. Если оператор
    PRIVATE задан без списка объектов модуля и нет объектов, для которых явно задан атрибут PUBLIC, то действие атрибута PRIVATE распространяется на все объекты модуля, даже если они объявлены до оператора PRIVATE. Например: module pupr
    ! Переменные a и b имеют атрибут PRIVATE real a private integer b
    Аналогичный эффект вызывает задание без списка объектов модуля оператора PUBLIC. В модуле может быть только один оператор без списка объектов модуля (PUBLIC или PRIVATE).
    Объекту не может быть дан атрибут PUBLIC, если он уже имеет атрибут
    PRIVATE.
    Родовое описание, если оно не имеет атрибут PRIVATE, является PUB-
    LIC, даже если одно или все его специфические имена объявлены
    PRIVATE.
    Если namelist-группа имеет атрибут PUBLIC, то ни один из ее компонентов не может иметь атрибут PRIVATE.
    Компоненты объявленного PUBLIC производного типа имеют атрибут
    PUBLIC, за исключением компонентов, которые имеют атрибут PRIVATE.
    Пример: module pupr type pri
    ! Все переменные типа pri будут private
    ! иметь атрибут PRIVATE integer ix, iy end type pri type, public :: pub real x, y type(pri) epin
    ! Этот компонент типа pub имеет end type pub
    ! атрибут PRIVATE type(pub), public :: ep = pub(3.0, 4.0, pri(3, 3))
    231

    О. В. Бартеньев. Современный ФОРТРАН
    real, public :: a = 3.0, b = 4.0 public :: length private :: square
    ! Подпрограмма square доступна contains ! только в модуле pupr real function length(x, y) real, intent(inout) :: x, y call square(x, y) length = sqrt(x + y) end function subroutine square(x1, y1) real, intent(inout) :: x1, y1 x1 = x1 * x1 y1 = y1 * y1 end subroutine end module pupr program gopu use pupr print *, length(ep%x, ep%y)
    ! 5.000000 print *, length(a, b)
    ! 5.000000 end
    8.10. Операторы заголовка процедур
    Полный синтаксис оператора заголовка подпрограммы:
    [RECURSIVE] SUBROUTINE имя подпрограммы
    &
    [([список формальных параметров])]
    Общий вид оператора заголовка функции:
    [type] [RECURSIVE] FUNCTION имя функции
    &
    ([список формальных параметров]) [RESULT (имя результата)]
    8.10.1. Общие характеристики операторов заголовка процедур
    Имя процедуры (подпрограммы и функции)может быть глобальным и внешним или внутренним в процедуре-носителе. Имя процедуры не может появляться в операторах AUTOMATIC, COMMON, EQUIVALENCE,
    DATA, INTRINSIC, NAMELIST, SAVE. Имя подпрограммы не может появляться в операторах объявления типа.
    Список формальных параметров может содержать имена переменных и формальных процедур. В случае подпрограммы формальным параметром может быть и обозначающая альтернативный возврат звездочка. Формаль-
    ные параметры могут отсутствовать, если передача данных выполняется посредством use-ассоциирования, ассоциирования через носитель или com-
    mon-блоки.
    Процедура может содержать любые операторы, кроме BLOCK DATA и PROGRAM. До оператора CONTAINS процедура не может содержать
    232

    8. Программные единицы операторы FUNCTION и SUBROUTINE. Внутренние процедуры не могут содержать операторы ENTRY и CONTAINS и другую внутреннюю процедуру. Внутренние процедуры размещаются между операторами CON-
    TAINS и END главной программы или процедуры-носителя.
    Если процедура внешняя, то ее имя является глобальными не должно совпадать с другим глобальным именем, а также не должно быть использовано для локального имени в вызывающей программной единице.
    В случае внутренней процедуры ее имя является локальным и область его действия ограничена носителем.
    Если формальный параметр имеет атрибут OPTIONAL, то при вызове соответствующий фактический параметр может быть опущен. Типы формальных параметров могут быть заданы внутри процедуры как неявно, так и явно (последнее предпочтительнее). Имена формальных параметров не могут появляться в операторах AUTOMATIC, COMMON, DATA,
    EQUIVALENCE, INTRINSIC, SAVE или STATIC.
    При вызове процедуры передаваемые фактические параметры должны быть согласованы с соответствующими формальными по порядку (за исключением случаев, когда используются вызовы с ключевыми словами), по числу (за исключением случаев, когда заданы атрибуты OPTIONAL или
    C), по типу и разновидности типа. Компилятор проверяет соответствие параметров. При обнаружении несоответствия, как правило, генерируются ошибки. Полная проверка соответствия фактических и формальных параметров выполняется компилятором при явном задании интерфейса к процедуре. Явным интерфейсом обладают модульные и внутренние процедуры.
    Полезно явно задавать интерфейс и к внешним процедурам, а в большом числе случаев он просто необходим (разд. 8.11.3).
    Если вызываемая процедура находится в динамической библиотеке
    (DLL), то необходимо задавать ее интерфейс и использовать с ней атрибуты
    DLLEXPORT или DLLIMPORT [1].
    Выход из процедуры осуществляется в результате выполнения либо оператора END, либо оператора RETURN. Последний может быть размещен где угодно среди исполняемых операторов процедуры.
    8.10.2. Результирующая переменная функции
    Функция обязана содержать результирующую переменную, в которую помещается возвращаемый функцией результат.
    Имя результирующей переменной задается предложением RESULT или совпадает с именем функции, если это предложение опущено.
    Задаваемое предложением RESULT имя результата не может совпадать с
    именем функции.
    Тип результирующей переменной определяет тип функции и может быть задан посредством указания type в заголовке функции.
    233

    О. В. Бартеньев. Современный ФОРТРАН
    type - объявление типа и разновидности типа результирующей переменной (возвращаемого функцией результата). Может быть любого встроенного типа.
    type может быть опущен. Тогда тип результирующей переменной может быть задан явно в одном из операторов объявления функции, в операторе
    IMPLICIT или неявно. Последнее невозможно, если заданы оператор IM-
    PLICIT NONE или директива $DECLARE.
    Если в операторе заголовка задан type, то имя результирующей переменной не должно появляться в разделе объявлений функции.
    Примеры объявления результирующей переменной: function imax(a, n)
    ! Результирующая переменная imax; integer a(n)
    ! ее тип INTEGER задан неявно
    ! Исполняемые операторы logical function flag(a, n)
    ! Результирующая переменная flag; integer a(n)
    ! ее тип LOGICAL задан явно function flag(a, n)
    ! Результирующая переменная flag; logical flag
    ! ее тип LOGICAL задан явно function flag(a, n) result(vf)
    ! Результирующая переменная vf; logical vf
    ! ее тип LOGICAL задан явно
    Если тип внешней функции определен без учета правил умолчаний о типах данных или заданы оператор IMPLICIT NONEили директива $DE-
    CLARE, то тип функции либо должен быть объявлен в вызывающей программной единице, либо там должен быть задан интерфейс к этой функции. На модульные и внутренние функции это требование не распространяется, поскольку они и без того имеют явно заданный интерфейс.
    Пример: logical function flag(a, n) result (vf) vf = ...
    ! Определяем значение результирующей переменной end program fude logical flag, fl
    ! Объявляем функцию flag в вызывающей программе
    ! Тип объявляемой функции определяется типом fl = flag(a, n)
    ! результирующей переменной end
    Если результатом функции является переменная производного типа, массив или ссылка, то type опускается и результирующая переменная объявляется в разделе объявлений функции.
    1   ...   21   22   23   24   25   26   27   28   ...   49


    написать администратору сайта