Fortran - 模块子程序参数Intent Confusion- INOUT vs OUT

时间:2014-09-15 11:27:11

标签: module scope fortran subroutine

让我们说有一个向量:

REAL(KIND=dp), DIMENSION(maxn) ::  rho

在初始子程序(以及dpmaxn)中分配值,并从主程序中调用。

主程序然后调用一个包含(不同的)子程序的模块来进化rhorho的子例程参数定义为:

SUBROUTINE sum_density(a, b, c, ....., rho)

在这个子程序中,rho被声明为:

REAL(KIND=dp), DIMENSION(maxn), INTENT(OUT)  ::  rho   

然而,在与rho

关联的任何值之前,代码包含以下行
foo1= foo2*foo3(i)/rho(i)

我原以为模块子程序无法访问主程序中定义的rho。我期望编译器抱怨并要求将意图更改为(INOUT)或者说rho之类的内容未定义。即使我将其更改为(INOUT),结果也没有差异。模块子例程必须访问主程序中rho的值并使用它,即使意图声明为OUT

我的问题是 - 在这种情况下,使用INTENT(OUT)INTENT(INOUT)之间的区别是什么?

1 个答案:

答案 0 :(得分:3)

使用INTENT(OUT)程序不符合标准,因为它访问具有未定义值的数组。

然而,由于通常实现显式形状数组的方式 - 通过传递数组的地址,软件实现可能会起作用。如果您传递的数组不连续,请说

  rho(::2)

编译器可能会创建一个副本,该副本会被传递并且您可能会遇到问题,因为该数组可能包含intent(out)的垃圾。

关于警告,它们不是强制性的,但如果您使用-warn-Wall等标记,编制者会对此发出警告。

对于intent(in),当您尝试修改rho时会出现差异。如果您尝试编译器必须发出错误。

关于范围:

在这里讨论范围并不正确,原始rho绝对不在子程序的范围内,只有伪参数。重复使用相同名称可能会令人困惑。想象一下,它们实际上在程序中被称为rho1,在子程序中被称为rho2。然后很明显rho1不在子程序的范围内,但是rho2是。

现在,rho2不能保证在rho1的子例程开头与intent(out)具有相同的值,但保证intent(inout)intent(out)保持一致。原因是可以使用copy-in和copy-out实现参数传递,并且module m contains subroutine sub(a2) real, intent(out) :: a2(4) print *,a2 a2 = 2 end subroutine end use m real :: a1(8) a1 = 1 call sub(a1(::2)) end 可以省略复制。

考虑以下代码:

sunf90 intent2.f90 
./a.out 
 5.879759E-39 0.0E+0 0.0E+0 0.0E+0

对于某些编译器,它会打印4次,正如人们所预料的那样,但是对于其他编译器参数,它会打印垃圾:

{{1}}