Module Fortran-模块子例程参数意图混淆-输入输出vs输出

Module Fortran-模块子例程参数意图混淆-输入输出vs输出,module,scope,fortran,subroutine,Module,Scope,Fortran,Subroutine,假设有一个向量: REAL(KIND=dp), DIMENSION(maxn) :: rho 在初始子例程中分配值(以及dp和maxn),并从主程序调用 然后,主程序调用一个包含(不同)子例程的模块来进化rho。rho的子例程参数定义为: SUBROUTINE sum_density(a, b, c, ....., rho) 在该子程序中,rho声明为: REAL(KIND=dp), DIMENSION(maxn), INTENT(OUT) :: rho 然而,在与rho关联的

假设有一个向量:

REAL(KIND=dp), DIMENSION(maxn) ::  rho
在初始子例程中分配值(以及
dp
maxn
),并从主程序调用

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

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

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

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

但是,由于显式形状数组通常是通过传递数组的地址来实现的,因此软件实现可能会起作用。如果传递的数组是非连续的,那么

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

关于警告,它们不是强制性的,但是如果使用诸如
-warn
-Wall
之类的标志,编译器会发出警告

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

关于范围:

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

现在,
rho2
不保证与
intent(out)
子例程开始时的
rho1
具有相同的值,但它保证具有
intent(inout)
。原因是参数传递可以使用copy-in和copy-out实现,而对于
intent(out)
,可以省略copy-in

考虑以下代码:

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
对于某些编译器,它会打印4次一次,正如人们所期望的那样,但是对于其他编译器或某些编译器参数,它会打印垃圾:

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

你在最后一句话中真的是指意图吗?哎呀,谢谢你指出了我的错误谢谢你的回答(也谢谢你在问题的最后一句中指出了我的打字错误)。因此,如果意图被声明为out,您能否澄清最初声明的rho是否通常超出模块的范围?您的意思是,由于显式形状数组的实现方式,它被纳入了范围?最初声明的
rho
在模块过程中永远不在范围内,无论
意图是什么。然而,与之关联的内存也与模块过程中的伪参数关联。