在Fortran中显示intent(out)和intent(inout)之间差异的有效程序

在Fortran中显示intent(out)和intent(inout)之间差异的有效程序,fortran,Fortran,这是我在SO上发现的一篇文章的后续内容: 链接的问题询问了Fortran中intent(out)和intent(inout)之间的区别,方法是询问一个 任何人都可以通过将intent(inout)更改为intent(out),或者反之亦然,想出一个简单有效的程序来给出不同的结果吗?给你 program intent_test implicit none integer, allocatable :: a(:) a = [1,2,3,4,5] call intent_inout (a) ca

这是我在SO上发现的一篇文章的后续内容:

链接的问题询问了Fortran中
intent(out)
intent(inout)
之间的区别,方法是询问一个

任何人都可以通过将
intent(inout)
更改为
intent(out)
,或者反之亦然,想出一个简单有效的程序来给出不同的结果吗?

给你

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
12345
未分配的

正如史蒂夫·莱昂内尔(Steve Lionel)所说,以及我原始答案中可能引发这种兴趣的评论,
意图(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
重要的是,组件的默认初始化意味着即使在进入
s2
之前,
x%x
也不是未定义的,但它在进入过程之前接受了一个可能与实际参数组件不同的值

使用指针参数编写一个合适的程序是很棘手的:在重新定义指针关联状态之前,无法引用/查询具有未定义指针关联状态的指针

这让我们看到了可分配组件。与指针不同,指针关联状态未定义时无法查询,我们可以询问分配状态。取消分配与
意图(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)
,以及没有指定的意图是Fortran程序员的关键部分。

+1。谢谢你的快速回复,史蒂夫!本例中使用了一个数组,@francescalus使用
type
执行“技巧”。这让我想知道,如果只使用只执行简单算术的
integer
变量和子例程,或者只使用
print
函数,那么
out
inout
是否可能总是给出相同的结果。(这当然是另一个问题。)我怀疑这不太可能。但是,通过一些示例,我没有发现任何差异。重要的是
ALLOCATABLE
属性-变量可以是任何类型。根据标准,
INTENT(OUT)
意味着伪参数的定义状态在进入过程时为“未定义”,但在其他情况下很难检测到。关于@francescalus对“disassociates”的使用——这让我感到不安,指针被解除关联
INTENT(OUT)
导致指针未定义,而不是解除关联,因此您不能假设甚至测试指针已解除关联。是的,我使用“disassociate”作为“成为未定义关联状态”的(懒惰)速记(有关更精确的状态,请参见我的答案)。请注意,“指针变为未定义”同样不精确:它未定义(这很好),但它的关联状态也未定义(这很好)。谢谢!在我看来,
intent(inout)
intent(out)之间的区别
非常微妙,虽然底层机制不同,但它们给出相同的结果可能并不罕见。需要记住的重要一点是,
INTENT
实际上是对程序员的一种帮助,它为编译器提供了额外的信息,可以用来提醒您可能出现的错误。例如,传递
INTENT(INOUT)
参数的常量是错误的,因为
INTENT(INOUT)
要求实际参数是可定义的。这不同于省略
INTENT
(我游说支持
INTENT(NONE)
与省略
INTENT
)和
INTENT(in)的含义相同
如果实际值未定义,编译器可能会警告您。我仍然有点困惑,在这两种情况下(inout或out)正确吗我仍然需要在主程序中声明变量?如果不在子例程中声明变量,子例程中的变量可能与主程序中的等效变量有不同的维度,或者没有?@Hermantouthrot,我不确定我是否理解你的问题。但是,让我们看看这是否有帮助:使用
intent(inout)
intent(out)
引用过程的地方(比如主程序)必须有一个对应的(可定义对象/)变量。有了这些意图,就不可能使用表达式作为参数。数组维度是否匹配与任何指定意图无关。(请注意,我这里的示例中没有数组。)