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
我的问题是-在这种情况下,使用InINTENT(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
在模块过程中永远不在范围内,无论意图是什么。然而,与之关联的内存也与模块过程中的伪参数关联。