Допустимые программы, показывающие разницу между намерением (выход) и намерением (вход) в Fortran - PullRequest
2 голосов
/ 06 ноября 2019

Это продолжение поста, который я нашел на SO: Разница между намерением (выход) и намерением (вход)

В связи с этим был задан вопрос о разнице между intent(out) и intent(inout) в Фортране, запрашивая недопустимую программу .

Может ли кто-нибудь придумать простую действительную программу (ы), которая дает другие результаты, если изменить intent(inout) на intent(out) или наоборот?

Ответы [ 2 ]

4 голосов
/ 06 ноября 2019

Вот, пожалуйста ...

program intent_test
implicit none
integer, allocatable :: a(:)

a = [1,2,3,4,5]

call intent_inout (a)

call intent_out (a)

contains

subroutine intent_inout (a)
integer, allocatable, intent(inout) :: a(:)

if (allocated(a)) then
  print *, a
else
  print *, "Unallocated"
end if

end subroutine intent_inout

subroutine intent_out (a)
integer, allocatable, intent(out) :: a(:)

if (allocated(a)) then
  print *, a
else
  print *, "Unallocated"
end if

end subroutine intent_out

end program intent_test

1 2 3 4 5 Unallocated

3 голосов
/ 06 ноября 2019

В ответе Стива Лайонела и комментариях в моем первоначальном ответе, которые, возможно, вызвали этот интерес, влияние intent(out) на начальное состояние фиктивного аргумента (и фактического аргумента) является одним из способовЧтобы ответить на этот вопрос.

intent(inout) имеет фиктивный аргумент, отражающий значение фактического аргумента при входе в процедуру. intent(out) "сбрасывает" фиктивный аргумент. В случае связанного вопроса это «неопределенность» является причиной неправильной природы программы.

Точнее, о intent(out) фиктивных аргументах можно сказать следующее:

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

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

  implicit none
  type t
     integer :: x=1
  end type t
  type(t) :: x=t(0)

  call s1(x)
  call s2(x)

contains
  subroutine s1(x)
    type(t), intent(inout) :: x
    print*, x%x
  end subroutine s1

  subroutine s2(x)
    type(t), intent(out) :: x
    print*, x%x
  end subroutine s2

end

Важно, что инициализация компонента по умолчанию означает, что x%x не является неопределенным даже при входе в s2, но оно потенциально может отличаться от фактического компонента аргумента до ввода процедуры.

Создать подходящую программу с аргументами-указателями довольно сложно: на указатель с неопределенным статусом ассоциации указателя нельзя ссылаться/ запрашивается до переопределения его статуса ассоциации указателей.

Что оставляет нас в поиске выделяемых компонентов. В отличие от указателей, где мы не можем запрашивать статус ассоциации указателя, когда он не определен, мы можем спросить о статусе выделения. Фактический аргумент, соответствующий манекену intent(out), освобождается;с intent(inout) статус распределения не изменяется:

  implicit none
  integer, allocatable :: i
  allocate (i)

  call s1(i); print*, allocated(i)
  call s2(i); print*, allocated(i)

contains

  subroutine s1(i)
    integer, allocatable, intent(inout) :: i
  end subroutine s1

  subroutine s2(i)
    integer, allocatable, intent(out) :: i
  end subroutine s2
end

(Это более простая версия примера Стива Лайонела.)

Все это показывает, что возможны различия. Неправильное использование intent может привести к неправильным программам или значительным изменениям в значении. Понимание того, что означают intent(in), intent(inout), intent(out) и отсутствие определенного намерения, является важной частью работы программиста на Фортране.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...